## [1] "!! high !! The experiment investigate the effects of two disturbance levels: low and high. To make it easier to interpet, we showcase only one of the two disturbance levels. In this document we showcase only the high disturbance)"
Ecosystem size is a key factor driving biodiversity and ecosystem function. Larger ecosystems contain more species and can be hubs of dispersal and resource flows in networks of multiple ecosystems. However, whether and how ecosystem size and resource flows interact to affect biodiversity and ecosystem function has been largely overlooked. Here, we investigated how ecosystem size asymmetry affects biodiversity and function of two-ecosystem meta-ecosystems connected through flows of non-living resources. We conducted microcosm experiments, mimicking resource flows between ecosystems of different sizes, yet otherwise being identical. We found that meta-ecosystems with asymmetric ecosystem sizes had higher β-diversity but lower α-diversity and ecosystem function (total biomass) than their unconnected counterparts, while such an effect was not found for meta-ecosystems of identical ecosystem sizes. Our work demonstrates of how cross-ecosystem dynamics modulated by differences in ecosystem sizes affect biodiversity and function, with a direct implication for conservation and management of connected ecosystems.
Parameters for R markdown and the general running of the code.
start_time = Sys.time()
knitr::opts_chunk$set(message = FALSE,
cache = FALSE,
autodep = FALSE)
recompute_lengthy_analyses = FALSE
plot_model_residuals_metaecos = FALSE
Parameters related to resource flows.
disturbance_levels = c("low", "high")
n_disturbance_levels = length(disturbance_levels)
resource_flow_days = c(5, 9, 13, 17, 21, 25)
first_resource_flow = resource_flow_days[1]
Parameters related to sampling.
total_frames = 125
volume_recorded_μl = 34.4
time_points = 0:7
time_points_without_t0 = 1:7
time_point_names = c("t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7")
sampling_days = c(0, 4, 8, 12, 16, 20, 24, 28)
first_time_point = 0
last_time_point = length(sampling_days) - 1
n_time_points = last_time_point + 1
nr_videos = c(12, 1, 1, 1, 1, 1, 2, 2) #Videos taken for each time point for each culture. At t0 we took 12 videos of the large bottle from which we started the cultures. Write why 2 at the end.
videos_taken = data.frame(time_point = 0 : 7,
nr_videos = c(12, 1, 1, 1, 1, 1, 2, 2))
n_videos_taken_t0 = nr_videos[1]
time_point_day = data.frame(time_point = first_time_point:last_time_point,
day = sampling_days,
video_replicates = nr_videos)
videos_to_take_off = data.frame(culture_ID = NA,
time_point = NA,
file = NA) %>%
add_row(culture_ID = 137-110,
time_point = 7,
file = 137) %>%
slice(-1)
n_cultures = 110
total_number_of_video_rows = sum(nr_videos * n_cultures)
Parameters related to protists.
protist_species = c("Ble", "Cep", "Col", "Eug", "Eup", "Lox", "Pau", "Pca", "Spi", "Spi_te", "Tet")
protist_species_indiv_per_volume = paste0(protist_species, "_indiv_per_volume")
protist_species_indiv_per_ml = paste0(protist_species, "_indiv_per_ml")
protist_species_dominance = paste0(protist_species_indiv_per_ml, "_dominance")
protist_species_total = paste0(protist_species, "_tot_indiv")
n_protist_species = length(protist_species)
first_protist = protist_species[1]
last_protist = protist_species[n_protist_species]
species_IDD_with_13_threshold = c("Col", "Eug", "Eup", "Lox", "Pau", "Pca", "Spi_te", "Tet")
species_IDD_with_13_threshold_indiv_per_volume = paste0(species_IDD_with_13_threshold, "_indiv_per_volume")
species_IDD_with_40_threshold = c("Ble", "Cep", "Spi")
species_IDD_with_40_threshold_indiv_per_volume = paste0(species_IDD_with_40_threshold, "_indiv_per_volume")
Parameters related to ecosystems.
ecosystems_to_take_off = 60 #Culture ID = 60 as it was spilled (small unconnected, high disturbance, system nr = 40)
ecosystems_info = read.csv(here("2_data", "ecosystems_info.csv"), header = TRUE)
columns_ecosystems = c("time_point",
"day",
"culture_ID",
"system_nr",
"disturbance",
"ecosystem_type",
"connection",
"ecosystem_size",
"ecosystem_size_ml",
"metaecosystem",
"metaecosystem_type")
columns_treatments = columns_ecosystems[!columns_ecosystems %in% c("system_nr", "culture_ID")]
variables_ecosystems = c("bioarea_mm2_per_ml",
"bioarea_tot_mm2",
"indiv_per_ml",
"indiv_tot",
"species_richness",
"shannon",
"simpson",
"inv_simpson",
"evenness_pielou",
"median_body_area_µm2",
paste0(protist_species, "_indiv_per_ml"),
paste0(protist_species, "_tot_indiv"),
paste0(protist_species_indiv_per_ml, "_dominance"))
baseline_columns = paste0("baseline_", variables_ecosystems)
ecosystem_types_ordered = c("Small connected to large",
"Small connected to small",
"Small unconnected",
"Medium connected to medium",
"Medium unconnected",
"Large connected to small",
"Large connected to large",
"Large unconnected")
treatments_and_controls = data.frame(treatment = c("Small connected to small",
"Small connected to large",
"Medium connected to medium",
"Large connected to large",
"Large connected to small"),
control = c("Small unconnected",
"Small unconnected",
"Medium unconnected",
"Large unconnected",
"Large unconnected"))
n_treatments = length(unique(treatments_and_controls$treatment))
n_controls = length(unique(treatments_and_controls$control))
n_replicates = 5
n_ecosystem_types = 8
Parameters related to size classes.
n_size_classes = 12
columns_classes = c(columns_ecosystems,
"size_class_n",
"mean_class_area_µm2")
Parameters related to meta-ecosystems.
metaecosystems_to_take_off = ecosystems_info %>%
filter(culture_ID %in% ecosystems_to_take_off) %>%
pull(system_nr) %>%
unique
system_nr_metaecosystems = ecosystems_info %>%
filter(metaecosystem == "yes") %>%
pull(system_nr) %>%
unique
n_metaecosystems = length(system_nr_metaecosystems)
variables_metaecos = c(
"total_metaecosystem_bioarea_mm2",
"jaccard_index",
"bray_curtis",
"beta_spatial_turnover",
"beta_nestedness",
"beta_total",
"metaecosystem_richness")
metaecosystem_types_ordered = c(
"Small-Small meta-ecosystem",
"Medium-Medium meta-ecosystem",
"Medium-Medium unconnected",
"Large-Large meta-ecosystem",
"Small-Large meta-ecosystem",
"Small-Large unconnected")
Name of the axes per response variable.
axis_names = data.frame(variable = NA,
axis_name= NA) %>%
add_row(variable = "day", axis_name = "Time (day)") %>%
add_row(variable = "ecosystem_size_ml", axis_name = "Patch size (ml)") %>%
add_row(variable = "log_size_class", axis_name = "Log size (μm2)") %>%
add_row(variable = "class_indiv_per_µl", axis_name = "Density (ind/ml)") %>%
add_row(variable = "bioarea_mm2_per_ml", axis_name = "Biomass (mm2/ml)") %>%
add_row(variable = "bioarea_mm2_per_ml_d", axis_name = "Bioamass ES") %>%
add_row(variable = "bioarea_tot", axis_name = "Total Biomass (mm2)") %>%
add_row(variable = "total_metaecosystem_bioarea_mm2", axis_name = "Total Biomass (mm2)") %>%
add_row(variable = "species_richness", axis_name = "Species Richness") %>%
add_row(variable = "species_richness_d", axis_name = "Species Richness ES") %>%
add_row(variable = "mean_richness", axis_name = "Mean α-Diversity (Shannon)") %>%
add_row(variable = "mean_shannon", axis_name = "Mean α-Diversity (Shannon)") %>%
add_row(variable = "shannon", axis_name = "Biodiversity (Shannon)") %>%
add_row(variable = "shannon_d", axis_name = "Biodiversity ES (Shannon ES)") %>%
add_row(variable = "bray_curtis", axis_name = "β-Diversity (Bray-Curtis)") %>%
add_row(variable = "beta_spatial_turnover", axis_name = "Turn over (Simpson pair-wise dissimilarity)") %>%
add_row(variable = "beta_nestedness", axis_name = "Nestedness (nestedness-fraction of Sorensen)") %>%
add_row(variable = "beta_total", axis_name = "Tot β-Diversity (Sorensen)") %>%
add_row(variable = "metaecosystem_richness", axis_name = "γ-Diversity (Species Richness)") %>%
add_row(variable = "indiv_per_ml", axis_name = "Abundance (ind/ml)") %>%
add_row(variable = "indiv_per_ml_d", axis_name = "Abundance ES") %>%
add_row(variable = "median_body_area_µm2", axis_name = "Median Body Size (µm²)") %>%
add_row(variable = "median_body_area_µm2_d", axis_name = "Median Body Size ES") %>%
add_row(variable = "Ble_indiv_per_ml", axis_name = "Ble Density (ind/ml)") %>%
add_row(variable = "Cep_indiv_per_ml", axis_name = "Cep Density (ind/ml)") %>%
add_row(variable = "Col_indiv_per_ml", axis_name = "Col Density (ind/ml)") %>%
add_row(variable = "Eug_indiv_per_ml", axis_name = "Eug Density (ind/ml)") %>%
add_row(variable = "Eup_indiv_per_ml", axis_name = "Eup Density (ind/ml)") %>%
add_row(variable = "Lox_indiv_per_ml", axis_name = "Lox Density (ind/ml)") %>%
add_row(variable = "Pau_indiv_per_ml", axis_name = "Pau Density (ind/ml)") %>%
add_row(variable = "Pca_indiv_per_ml", axis_name = "Pca Density (ind/ml)") %>%
add_row(variable = "Spi_indiv_per_ml", axis_name = "Spi Density (ind/ml)") %>%
add_row(variable = "Spi_te_indiv_per_ml", axis_name = "Spi te Density (ind/ml)") %>%
add_row(variable = "Tet_indiv_per_ml", axis_name = "Tet Density (ind/ml)") %>%
add_row(variable = "auto_hetero_ratio", axis_name = "Photosynthetisers-Heterotrops Ratio") %>%
add_row(variable = "Ble_indiv_per_ml_d", axis_name = "Ble Density ES") %>%
add_row(variable = "Cep_indiv_per_ml_d", axis_name = "Cep Density ES") %>%
add_row(variable = "Col_indiv_per_ml_d", axis_name = "Col Density ES") %>%
add_row(variable = "Eug_indiv_per_ml_d", axis_name = "Eug Density ES") %>%
add_row(variable = "Eup_indiv_per_ml_d", axis_name = "Eup Density ES") %>%
add_row(variable = "Lox_indiv_per_ml_d", axis_name = "Lox Density ES") %>%
add_row(variable = "Pau_indiv_per_ml_d", axis_name = "Pau Density ES") %>%
add_row(variable = "Pca_indiv_per_ml_d", axis_name = "Pca Density ES") %>%
add_row(variable = "Spi_indiv_per_ml_d", axis_name = "Spi Density ES") %>%
add_row(variable = "Spi_te_indiv_per_ml_d", axis_name = "Spi te Density ES") %>%
add_row(variable = "Tet_indiv_per_ml_d", axis_name = "Tet Density ES") %>%
add_row(variable = "Ble_indiv_per_ml_dominance", axis_name = "Ble Dominance (%)") %>%
add_row(variable = "Cep_indiv_per_ml_dominance", axis_name = "Cep Dominance (%)") %>%
add_row(variable = "Col_indiv_per_ml_dominance", axis_name = "Col Dominance (%)") %>%
add_row(variable = "Eug_indiv_per_ml_dominance", axis_name = "Eug Dominance (%)") %>%
add_row(variable = "Eup_indiv_per_ml_dominance", axis_name = "Eup Dominance (%)") %>%
add_row(variable = "Lox_indiv_per_ml_dominance", axis_name = "Lox Dominance (%)") %>%
add_row(variable = "Pau_indiv_per_ml_dominance", axis_name = "Pau Dominance (%)") %>%
add_row(variable = "Pca_indiv_per_ml_dominance", axis_name = "Pca Dominance (%)") %>%
add_row(variable = "Spi_indiv_per_ml_dominance", axis_name = "Spi Dominance (%)") %>%
add_row(variable = "Spi_te_indiv_per_ml_dominance", axis_name = "Spi te Dominance (%)") %>%
add_row(variable = "Tet_indiv_per_ml_dominance", axis_name = "Tet Dominance (%)") %>%
add_row(variable = "Ble_indiv_per_ml_dominance_d", axis_name = "Ble Dominance ES") %>%
add_row(variable = "Cep_indiv_per_ml_dominance_d", axis_name = "Cep Dominance ES") %>%
add_row(variable = "Col_indiv_per_ml_dominance_d", axis_name = "Col Dominance ES") %>%
add_row(variable = "Eug_indiv_per_ml_dominance_d", axis_name = "Eug Dominance ES") %>%
add_row(variable = "Eup_indiv_per_ml_dominance_d", axis_name = "Eup Dominance ES") %>%
add_row(variable = "Lox_indiv_per_ml_dominance_d", axis_name = "Lox Dominance ES") %>%
add_row(variable = "Pau_indiv_per_ml_dominance_d", axis_name = "Pau Dominance ES") %>%
add_row(variable = "Pca_indiv_per_ml_dominance_d", axis_name = "Pca Dominance ES") %>%
add_row(variable = "Sp_indiv_per_mli_dominance_d", axis_name = "Spi Dominance ES") %>%
add_row(variable = "Spi_te_indiv_per_ml_dominance_d", axis_name = "Spi te Dominance ES") %>%
add_row(variable = "Tet_indiv_per_ml_dominance_d", axis_name = "Tet Dominance ES") %>%
add_row(variable = "dominance", axis_name = "Dominance (%)") %>%
add_row(variable = "log_abundance", axis_name = "Log Abundance + 1 (ind/mm²)") %>%
add_row(variable = "abundance_hedges_d", axis_name = "Density ES") %>%
add_row(variable = "beta_diversity_from_unconnected", axis_name = "Divergence from unconnected") %>%
add_row(variable = "beta_diversity_from_previous_time", axis_name = "Temporal Divergence") %>%
add_row(variable = "beta_diversity_from_previous_time_d", axis_name = "Temporal Divergence ES") %>%
add_row(variable = "evenness_pielou", axis_name = "Evenness") %>%
add_row(variable = "evenness_pielou_d", axis_name = "Evenness ES") %>%
slice(-1)
Colour and line type per ecosystem/meta-ecosystem type.
treatment_colours = c("Small" = "#feb24c",
"Medium" = "#1b7837",
"Large" = "#3182bd",
"Small-Small" = "#fc9272",
"Large-Large" = "#67000d",
"Small-Large" = "#762a83",
"Medium-Medium" = "#1b7837",
"symmetric" = "#1b7837",
"asymmetric" = "#762a83")
treatment_linetype = c("connected to small" = "solid",
"connected to medium" = "dashed",
"connected to large" = "longdash",
"connected" = "solid",
"unconnected" = "dotted")
Parameters for plotting.
figures_height_rmd_output = 7
legend_position = "top"
legend_width_cm = 2
size_legend = 12
size_x_axis = 13
size_y_axis = size_x_axis
boxplot_width = 2
dodging = 0.5
width_errorbar = 0.2
dodging_error_bar = 0.5
treatment_lines_linewidth = 1
treatment_points_size = 2.5
resource_flow_line_type = "solid"
resource_flow_line_colour = "#d9d9d9"
resource_flow_line_width = 0.3
zero_line_colour = "grey"
zero_line_line_type = "dotted"
zero_line_line_width = 0.5
zero_line_ES_line_type = "dotted"
zero_line_ES_colour = "grey"
zero_line_ES_line_width = 1
ggarrange_margin_top = 0
ggarrange_margin_bottom = 0
ggarrange_margin_left = 0
ggarrange_margin_right = 0
paper_width = 17.3
paper_height = 20
paper_units = "cm"
paper_res = 600
paper_y_axis_size = 9
paper_labels_size = 9
presentation_figure_size = 15
presentation_figure_width = 30
presentation_figure_height = 22
presentation_legend_size = 20
presentation_x_axis_size = 22
presentation_y_axis_size = presentation_x_axis_size
presentation_axes_size = 12
presentation_treatment_points_size = 5
presentation_treatment_linewidth = 2
presentation_figure_units = "cm"
presentation_figure_res = 600
grey_background_xmin = -Inf
grey_background_xmax = 7.5
grey_background_ymin = -Inf
grey_background_ymax = Inf
grey_background_fill = "#f0f0f0"
grey_background_alpha = 0.03
grey_background_color = "transparent"
Parameters for modelling.
time_point_of_baselines = 1
time_points_with_water_addtion = 3:7
time_points_model = time_points_with_water_addtion
optimizer_input = 'Nelder_Mead'
method_input = ''
ecosystems_info)We start by importing the information about the 110 ecosystems of the experiment.
ecosystems_info = read.csv(here("2_data", "ecosystems_info.csv"), header = TRUE)
In this dataset (ds_individuals) each row represents an
individual at a time point.
# Import the individual data of t0. We considered cultures to be all the same at the beginning (t0). Because of this reason, we filmed only the bottles from which cultures were assembled. Because we want to plot also t0 for the different treatments, we want to assign the video of bottles to all cultures at t0.
ds_individuals_t0_not_elongated = read.csv(here("2_data",
"individuals_13_threshold",
"t0.csv")) %>%
mutate(time_point = as.numeric(str_extract(time_point, "\\d+")),
day = 0,
file = as.numeric(str_extract(file, "\\d+")),
video_replicate = file) %>%
select(time_point,
day,
video_replicate,
file,
id,
N_frames,
mean_area)
ds_individuals_t0_elongated = ds_individuals_t0_not_elongated %>%
map_dfr(.x = 1 : nrow(ecosystems_info),
.f = ~ ds_individuals_t0_not_elongated) %>%
arrange(id) %>% #Id refers to an individual
mutate(culture_ID = rep(1 : nrow(ecosystems_info),
times = nrow(ds_individuals_t0_not_elongated))) %>%
select(time_point,
day,
video_replicate,
file,
culture_ID,
id,
N_frames,
mean_area)
expect_equal(nrow(ds_individuals_t0_not_elongated) * nrow(ecosystems_info),
nrow(ds_individuals_t0_elongated))
#Import t1-t4
ds_individuals_t1_to_t4 = NULL
for (time_point_i in time_points_without_t0) {
ds_individuals_t1_to_t4[[time_point_i]] = read.csv(here("2_data",
"individuals_13_threshold",
paste0("t",
time_point_i,
".csv"))) %>%
mutate(time_point = as.numeric(str_extract(time_point, "\\d+")),
day = time_point_day$day[time_point_day$time_point == time_point_i],
file = as.numeric(str_extract(file, "\\d+")),
video_replicate = ceiling(file/n_cultures)) #Until 110 video replicate = 1, then 2
}
ds_individuals_t1_to_t4 = ds_individuals_t1_to_t4 %>%
bind_rows() %>%
select(time_point,
day,
video_replicate,
file,
culture_ID,
id,
N_frames,
mean_area)
# Bind t0 with t1-t4
ds_individuals = rbind(ds_individuals_t0_elongated,
ds_individuals_t1_to_t4) %>%
left_join(ecosystems_info,
by = "culture_ID")
# Rename and select columns
ds_individuals = ds_individuals %>%
rename(ecosystem_size = patch_size,
ecosystem_size_volume = patch_size_volume) %>%
select(
disturbance,
disturbance_volume,
time_point,
day,
video_replicate,
culture_ID,
system_nr,
file,
eco_metaeco_type,
ecosystem_size,
ecosystem_size_volume,
metaecosystem,
metaecosystem_type,
mean_area,
N_frames
) %>%
rename(ecosystem_size_ml = ecosystem_size_volume,
ecosystem_type = eco_metaeco_type,
body_area_µm2 = mean_area)
# Rename and reorder levels
ds_individuals <- ds_individuals %>%
mutate(ecosystem_type = case_when(ecosystem_type == "S" ~ "Small unconnected",
ecosystem_type == "M" ~ "Medium unconnected",
ecosystem_type == "L" ~ "Large unconnected",
ecosystem_type == "S (S_S)" ~ "Small connected to small",
ecosystem_type == "S (S_L)" ~ "Small connected to large",
ecosystem_type == "M (M_M)" ~ "Medium connected to medium",
ecosystem_type == "L (S_L)" ~ "Large connected to small",
ecosystem_type == "L (L_L)" ~ "Large connected to large",
TRUE ~ ecosystem_type),
ecosystem_type = factor(ecosystem_type,
levels = ecosystem_types_ordered))
ds_individuals <- ds_individuals %>%
mutate(ecosystem_size = case_when(ecosystem_size == "S" ~ "Small",
ecosystem_size == "M" ~ "Medium",
ecosystem_size == "L" ~ "Large",
TRUE ~ ecosystem_type),
ecosystem_size = factor(ecosystem_size,
levels = "Small",
"Medium",
"Large"))
ds_individuals <- ds_individuals %>%
mutate(size_connected_ecosystem = case_when(ecosystem_type == "Small connected to small" ~ "Small",
ecosystem_type == "Small connected to large" ~ "Large",
ecosystem_type == "Medium connected to medium" ~ "Medium",
ecosystem_type == "Large connected to large" ~ "Large",
ecosystem_type == "Large connected to small" ~ "Small",
TRUE ~ NA_character_))
# Take off problematic videos
ds_individuals_before_taking_off_videos = ds_individuals
ds_individuals = ds_individuals %>%
filter(!(time_point %in% videos_to_take_off$time_point & file %in% videos_to_take_off$file))
diff = setdiff(ds_individuals_before_taking_off_videos, ds_individuals)
expect_equal(nrow(videos_to_take_off),
nrow(expand.grid(diff$culture_ID, diff$time_point, diff$file) %>% unique()))
# Take off problematic cultures
ds_individuals_before_taking_off_cultures = ds_individuals
ds_individuals = ds_individuals %>%
filter(!culture_ID %in% ecosystems_to_take_off)
expect_equal(setdiff(ds_individuals_before_taking_off_cultures,
ds_individuals) %>%
pull(culture_ID) %>%
unique(),
ecosystems_to_take_off)
ds_ecosystems)In this dataset (ds_ecosystems) each row represents a
ecosystem at a time point. I use the data from the 40 threshold analysis
for Ble, Cep, Spi and the data from the 13 threshold analysis for all
the other protists (Col, Eup, Lox, Pau, Pca, Spi te, Tet).
# Import & bind t0 datasets.
ds_ecosystems_t0 = read.csv(here("2_data",
"ecosystems_13_threshold",
"t0.csv")) %>%
mutate(time_point = as.numeric(str_extract(time_point, "\\d+")),
day = 0,
video_replicate = file) %>%
select(time_point,
day,
video_replicate,
file,
bioarea_per_volume,
indiv_per_volume)
species_ID_13_threshold_t0 = read.csv(here("2_data",
"species_ID_13_threshold",
paste0("t0.csv"))) %>%
rename(Ble_indiv_per_volume = Ble,
Cep_indiv_per_volume = Cep,
Col_indiv_per_volume = Col,
Eug_indiv_per_volume = Eug,
Eup_indiv_per_volume = Eup,
Lox_indiv_per_volume = Lox,
Pau_indiv_per_volume = Pau,
Pca_indiv_per_volume = Pca,
Spi_indiv_per_volume = Spi,
Spi_te_indiv_per_volume = Spi_te,
Tet_indiv_per_volume = Tet) %>%
select(file,
all_of(species_IDD_with_13_threshold_indiv_per_volume))
species_ID_40_threshold_t0 = read.csv(here("2_data",
"species_ID_40_threshold",
paste0("t0.csv"))) %>%
rename(Ble_indiv_per_volume = Ble,
Cep_indiv_per_volume = Cep,
Col_indiv_per_volume = Col,
Eug_indiv_per_volume = Eug,
Eup_indiv_per_volume = Eup,
Lox_indiv_per_volume = Lox,
Pau_indiv_per_volume = Pau,
Pca_indiv_per_volume = Pca,
Spi_indiv_per_volume = Spi,
Spi_te_indiv_per_volume = Spi_te,
Tet_indiv_per_volume = Tet) %>%
select(file,
all_of(species_IDD_with_40_threshold_indiv_per_volume))
ds_ecosystems_t0 = ds_ecosystems_t0 %>%
left_join(species_ID_13_threshold_t0,
by = "file") %>%
left_join(species_ID_40_threshold_t0,
by = "file") %>%
mutate(file = as.numeric(str_extract(file, "\\d+")))
# Elongate t0 dataset.
ds_ecosystems_t0_elongated <- list()
for (video_i in 1 : n_videos_taken_t0) {
single_video = ds_ecosystems_t0 %>%
filter(file == video_i)
ds_ecosystems_t0_elongated[[video_i]] = ecosystems_info %>%
mutate(time_point = 0,
day = 0,
file = single_video$file,
video_replicate = single_video$video_replicate,
bioarea_per_volume = single_video$bioarea_per_volume,
indiv_per_volume = single_video$indiv_per_volume,
Ble_indiv_per_volume = single_video$Ble_indiv_per_volume,
Cep_indiv_per_volume = single_video$Cep_indiv_per_volume,
Col_indiv_per_volume = single_video$Col_indiv_per_volume,
Eug_indiv_per_volume = single_video$Eug_indiv_per_volume,
Eup_indiv_per_volume = single_video$Eup_indiv_per_volume,
Lox_indiv_per_volume = single_video$Lox_indiv_per_volume,
Pau_indiv_per_volume = single_video$Pau_indiv_per_volume,
Pca_indiv_per_volume = single_video$Pca_indiv_per_volume,
Spi_indiv_per_volume = single_video$Spi_indiv_per_volume,
Spi_te_indiv_per_volume = single_video$Spi_te_indiv_per_volume,
Tet_indiv_per_volume = single_video$Tet_indiv_per_volume)
}
ds_ecosystems_t0_elongated = ds_ecosystems_t0_elongated %>%
bind_rows()
# Clean the columns of t0
ds_ecosystems_t0 = ds_ecosystems_t0_elongated %>%
select(file,
time_point,
day,
culture_ID,
video_replicate,
bioarea_per_volume,
indiv_per_volume,
all_of(protist_species_indiv_per_volume))
expect_equal(nrow(ds_ecosystems_t0),
sum(n_videos_taken_t0 * n_cultures))
# Import and bind t1-t4
ds_ecosystems_t1_to_t4 = NULL
for (time_point_i in time_points_without_t0) {
species_ID_13_threshold = read.csv(here("2_data",
"species_ID_13_threshold",
paste0("t", time_point_i, ".csv"))) %>%
rename(Ble_indiv_per_volume = Ble,
Cep_indiv_per_volume = Cep,
Col_indiv_per_volume = Col,
Eug_indiv_per_volume = Eug,
Eup_indiv_per_volume = Eup,
Lox_indiv_per_volume = Lox,
Pau_indiv_per_volume = Pau,
Pca_indiv_per_volume = Pca,
Spi_indiv_per_volume = Spi,
Spi_te_indiv_per_volume = Spi_te,
Tet_indiv_per_volume = Tet) %>%
select(file,
all_of(species_IDD_with_13_threshold_indiv_per_volume))
species_ID_40_threshold = read.csv(here("2_data",
"species_ID_40_threshold",
paste0("t", time_point_i, ".csv"))) %>%
rename(Ble_indiv_per_volume = Ble,
Cep_indiv_per_volume = Cep,
Col_indiv_per_volume = Col,
Eug_indiv_per_volume = Eug,
Eup_indiv_per_volume = Eup,
Lox_indiv_per_volume = Lox,
Pau_indiv_per_volume = Pau,
Pca_indiv_per_volume = Pca,
Spi_indiv_per_volume = Spi,
Spi_te_indiv_per_volume = Spi_te,
Tet_indiv_per_volume = Tet) %>%
select(file,
all_of(species_IDD_with_40_threshold_indiv_per_volume))
ds_ecosystems_t1_to_t4[[time_point_i]] = read.csv(here("2_data",
"ecosystems_13_threshold",
paste0("t", time_point_i, ".csv"))) %>%
arrange(file) %>%
mutate(video_replicate = rep(1 : time_point_day$video_replicates[time_point_i+1],
each = n_cultures),
day = time_point_day$day[time_point_day$time_point == time_point_i]) %>%
select(file,
time_point,
day,
video_replicate,
file,
culture_ID,
bioarea_per_volume,
indiv_per_volume)
ds_ecosystems_t1_to_t4[[time_point_i]] = ds_ecosystems_t1_to_t4[[time_point_i]] %>%
left_join(species_ID_13_threshold,
by = "file") %>%
left_join(species_ID_40_threshold,
by = "file")
}
ds_ecosystems_t1_to_t4 = ds_ecosystems_t1_to_t4 %>%
bind_rows()
# Bind t0 with t1-t4
ds_ecosystems = rbind(ds_ecosystems_t0,
ds_ecosystems_t1_to_t4) %>%
left_join(ecosystems_info,
by = "culture_ID")
expect_equal(nrow(ds_ecosystems),
sum(sum(time_point_day$video_replicates) * n_cultures))
# Reorder and rename columns
ds_ecosystems = ds_ecosystems %>%
rename(ecosystem_size = patch_size,
ecosystem_size_ml = patch_size_volume) %>%
select(file,
time_point,
day,
disturbance,
culture_ID,
system_nr,
eco_metaeco_type,
ecosystem_size,
ecosystem_size_ml,
metaecosystem,
metaecosystem_type,
video_replicate,
bioarea_per_volume,
indiv_per_volume,
all_of(protist_species_indiv_per_volume)) %>%
rename(bioarea_µm2_per_μL = bioarea_per_volume) %>%
rename_all( ~ gsub("volume", "μL", .))
# Rename and reorder levels
ds_ecosystems <- ds_ecosystems %>%
mutate(ecosystem_size = case_when(ecosystem_size == "S" ~ "Small",
ecosystem_size == "M" ~ "Medium",
ecosystem_size == "L" ~ "Large",
TRUE ~ ecosystem_size),
connection = case_when(eco_metaeco_type == "S" ~ "unconnected",
eco_metaeco_type == "M" ~ "unconnected",
eco_metaeco_type == "L" ~ "unconnected",
eco_metaeco_type == "S (S_S)" ~ "connected to small",
eco_metaeco_type == "S (S_L)" ~ "connected to large",
eco_metaeco_type == "M (M_M)" ~ "connected to medium",
eco_metaeco_type == "L (S_L)" ~ "connected to small",
eco_metaeco_type == "L (L_L)" ~ "connected to large"),
ecosystem_type = paste(ecosystem_size, connection),
metaecosystem_type = case_when(metaecosystem_type == "S_S" ~ "Small-Small",
metaecosystem_type == "M_M" ~ "Medium-Medium",
metaecosystem_type == "L_L" ~ "Large-Large",
metaecosystem_type == "S_L" ~ "Small-Large",
TRUE ~ metaecosystem_type),
time_point = as.numeric(str_extract(time_point, "\\d+")),
file = as.numeric(str_extract(file, "\\d+")))
# Change units of measurments to ml
ds_ecosystems = ds_ecosystems %>%
mutate(bioarea_µm2_per_ml = bioarea_µm2_per_μL * 10^3,
bioarea_mm2_per_ml = bioarea_µm2_per_ml * 10^(-6),
Ble_indiv_per_ml = Ble_indiv_per_μL * 10^3,
Cep_indiv_per_ml = Cep_indiv_per_μL * 10^3,
Col_indiv_per_ml = Col_indiv_per_μL * 10^3,
Eug_indiv_per_ml = Eug_indiv_per_μL * 10^3,
Eup_indiv_per_ml = Eup_indiv_per_μL * 10^3,
Lox_indiv_per_ml = Lox_indiv_per_μL * 10^3,
Pau_indiv_per_ml = Pau_indiv_per_μL * 10^3,
Pca_indiv_per_ml = Pca_indiv_per_μL * 10^3,
Spi_indiv_per_ml = Spi_indiv_per_μL * 10^3,
Spi_te_indiv_per_ml = Spi_te_indiv_per_μL * 10^3,
Tet_indiv_per_ml = Tet_indiv_per_μL * 10^3)
# Take off problematic videos
ds_ecosystems_before_taking_off_videos = ds_ecosystems
ds_ecosystems = ds_ecosystems %>%
filter(!(time_point %in% videos_to_take_off$time_point & file %in% videos_to_take_off$file))
diff = setdiff(ds_ecosystems_before_taking_off_videos, ds_ecosystems)
expect_equal(nrow(videos_to_take_off),
nrow(expand.grid(diff$culture_ID, diff$time_point, diff$file) %>% unique()))
# Take off problematic cultures
ds_ecosystems_before_taking_off_cultures = ds_ecosystems
ds_ecosystems = ds_ecosystems %>%
filter(!culture_ID %in% ecosystems_to_take_off)
expect_equal(setdiff(ds_ecosystems_before_taking_off_cultures,
ds_ecosystems) %>%
pull(culture_ID) %>%
unique(),
ecosystems_to_take_off)
# Average videos
ds_ecosystems = ds_ecosystems %>%
group_by(across(all_of(columns_ecosystems))) %>%
summarise(across(contains("_per_ml"), mean),
across(contains("_tot"), mean)) %>%
ungroup()
expect_equal(nrow(ds_ecosystems),
(n_cultures - length(ecosystems_to_take_off)) * length(time_points))
# Add connection and individuals
ds_ecosystems = ds_ecosystems %>%
mutate(indiv_per_ml = !!rlang::parse_expr(paste(protist_species_indiv_per_ml,
collapse = " + ")))
# Calculate total response variable for the whole ecosystem
ds_ecosystems = ds_ecosystems %>%
mutate(bioarea_tot_mm2 = bioarea_mm2_per_ml * ecosystem_size_ml,
indiv_tot = indiv_per_ml * ecosystem_size_ml,
Ble_tot_indiv = Ble_indiv_per_ml * ecosystem_size_ml,
Cep_tot_indiv = Cep_indiv_per_ml * ecosystem_size_ml,
Col_tot_indiv = Col_indiv_per_ml * ecosystem_size_ml,
Eug_tot_indiv = Eug_indiv_per_ml * ecosystem_size_ml,
Eup_tot_indiv = Eup_indiv_per_ml * ecosystem_size_ml,
Lox_tot_indiv = Lox_indiv_per_ml * ecosystem_size_ml,
Pau_tot_indiv = Pau_indiv_per_ml * ecosystem_size_ml,
Pca_tot_indiv = Pca_indiv_per_ml * ecosystem_size_ml,
Spi_tot_indiv = Spi_indiv_per_ml * ecosystem_size_ml,
Spi_te_tot_indiv = Spi_te_indiv_per_ml * ecosystem_size_ml,
Tet_tot_indiv = Tet_indiv_per_ml * ecosystem_size_ml)
# Calculate species dominance
ds_ecosystems = ds_ecosystems %>%
mutate(across(.cols = all_of(protist_species_indiv_per_ml),
.fns = list(dominance = ~ (. / indiv_per_ml) * 100),
.names = "{col}_dominance"))
expect_equal(unique(ds_ecosystems$Ble_indiv_per_ml_dominance[ds_ecosystems$indiv_per_ml == 0]), NaN)
if (FALSE %in% unique((ds_ecosystems$Ble_indiv_per_ml/ds_ecosystems$indiv_per_ml) *100 == ds_ecosystems$Ble_indiv_per_ml_dominance)) stop()
# Calculate alpha diversity (Shannon, Simpson, Inverse Simpson, Evenness)
n_rows_ds_ecosystems_before_calculating_alpha = nrow(ds_ecosystems)
ds_ecosystems = calculate.alpha.diversity()
expect_equal(max(ds_ecosystems$species_richness),
length(protist_species))
expect_equal(nrow(ds_ecosystems),
n_rows_ds_ecosystems_before_calculating_alpha)
# Calculate median body size
n_rows_ds_ecosystems_before_median_size = nrow(ds_ecosystems)
ds_median_body_size = ds_individuals %>%
group_by(time_point,
culture_ID,
file) %>%
summarise(median_body_area_µm2 = median(body_area_µm2)) %>%
group_by(time_point,
culture_ID) %>%
summarise(median_body_area_µm2 = mean(median_body_area_µm2))
expect_true(nrow(ds_median_body_size) <= nrow(ds_ecosystems)) #Ds median body size could be less because some cultures might be crashed and not have any individual.
ds_ecosystems_before_full_join = ds_ecosystems
ds_ecosystems = full_join(ds_ecosystems, ds_median_body_size)
expect_equal(nrow(ds_ecosystems),
n_rows_ds_ecosystems_before_median_size)
# Calculate auto/heterotrophic ratio
ds_ecosystems = ds_ecosystems %>%
mutate(auto_hetero_ratio = (Eug_indiv_per_ml + Eup_indiv_per_ml) /
(Ble_indiv_per_ml +
Cep_indiv_per_ml +
Col_indiv_per_ml +
Lox_indiv_per_ml +
Pau_indiv_per_ml +
Pca_indiv_per_ml +
Spi_indiv_per_ml +
Spi_te_indiv_per_ml +
Tet_indiv_per_ml))
# Add evaporation rates
ds_for_evaporation = read.csv(here("2_data", "water_addition.csv")) %>%
pivot_longer(cols = starts_with("water_add_after_t"),
names_to = "time_point",
values_to = "water_addition_ml") %>%
mutate(time_point = as.double(str_extract(time_point, "\\d+")) + 1)
ds_ecosystems = ds_ecosystems %>%
left_join(ds_for_evaporation)
ds_ecosystems_effect_size)In this dataset (ds_ecosystems_effect_size) each row
represents a treatment at a time point. It contains the effect size of
the connection of a ecosystem (connected vs unconnected).
# Calculate the mean & sd of response variables for each treatment/control at each time point
ds_ecosystems_effect_size = NULL
variable_nr = 0
for (variable_i in variables_ecosystems) {
variable_nr = variable_nr + 1
ds_ecosystems_effect_size[[variable_nr]] = ds_ecosystems %>%
filter(time_point >= 1,
!is.na(!!sym(variable_i))) %>%
group_by(across(all_of(columns_ecosystems[columns_ecosystems != "culture_ID" &
columns_ecosystems != "system_nr"]))) %>%
summarise(across(all_of(variable_i),
list(mean = mean,
sd = sd)),
sample_size = n()) %>%
rename_with( ~ paste0(variable_i, "_sample_size"),
matches("sample_size"))
}
ds_ecosystems_effect_size <- reduce(ds_ecosystems_effect_size,
full_join,
by = columns_ecosystems[columns_ecosystems != "culture_ID" & columns_ecosystems != "system_nr"])
expect_equal(nrow(ds_ecosystems_effect_size),
n_ecosystem_types * (n_time_points-1) * n_disturbance_levels)
# Calculate the effect size (Hedge's d) for each treatment at each time point
for (variable_i in variables_ecosystems) {
ds_ecosystems_effect_size <- ds_ecosystems_effect_size %>%
mutate(!!paste0(variable_i, "_d") := NA,
!!paste0(variable_i, "_d_upper") := NA,
!!paste0(variable_i, "_d_lower") := NA)
}
row_i = 0
for (treatment_selected in treatments_and_controls$treatment) {
for (time_point_selected in time_points) {
row_i = row_i + 1
control_input = treatments_and_controls$control[treatments_and_controls$treatment == treatment_selected]
treatment_row = ds_ecosystems_effect_size %>%
filter(ecosystem_type == treatment_selected,
time_point == time_point_selected)
control_row = ds_ecosystems_effect_size %>%
filter(ecosystem_type == control_input,
time_point == time_point_selected)
for (response_variable in variables_ecosystems) {
hedges_d = calculate.hedges_d(treatment_row[[paste0(response_variable, "_mean")]],
treatment_row[[paste0(response_variable, "_sd")]],
treatment_row[[paste0(response_variable, "_sample_size")]],
control_row[[paste0(response_variable, "_mean")]],
control_row[[paste0(response_variable, "_sd")]],
control_row[[paste0(response_variable, "_sample_size")]])
ds_ecosystems_effect_size[[paste0(response_variable, "_d")]][
ds_ecosystems_effect_size$ecosystem_type == treatment_selected &
ds_ecosystems_effect_size$time_point == time_point_selected] =
hedges_d$d
ds_ecosystems_effect_size[[paste0(response_variable, "_d_upper")]][
ds_ecosystems_effect_size$ecosystem_type == treatment_selected &
ds_ecosystems_effect_size$time_point == time_point_selected] =
hedges_d$upper_CI
ds_ecosystems_effect_size[[paste0(response_variable, "_d_lower")]][
ds_ecosystems_effect_size$ecosystem_type == treatment_selected &
ds_ecosystems_effect_size$time_point == time_point_selected] =
hedges_d$lower_CI
}
}
}
expect_equal(nrow(ds_ecosystems_effect_size),
n_ecosystem_types * (n_time_points-1) * n_disturbance_levels)
ds_metaecosystems)In this dataset (ds_metaecosystems) each row represents
a meta-ecosystem or a two-ecosystem unconnected system at a time
point.
# --- Find the IDs of unconnected ecosystems --- #
ID_unconnected_S_low = ds_ecosystems %>%
filter(ecosystem_type == "Small unconnected",
disturbance == "low") %>%
pull(culture_ID) %>%
unique()
ID_unconnected_M_low = ds_ecosystems %>%
filter(ecosystem_type == "Medium unconnected",
disturbance == "low") %>%
pull(culture_ID) %>%
unique()
ID_unconnected_L_low = ds_ecosystems %>%
filter(ecosystem_type == "Large unconnected",
disturbance == "low") %>%
pull(culture_ID) %>%
unique()
ID_unconnected_S_high = ds_ecosystems %>%
filter(ecosystem_type == "Small unconnected",
disturbance == "high") %>%
pull(culture_ID) %>%
unique()
ID_unconnected_M_high = ds_ecosystems %>%
filter(ecosystem_type == "Medium unconnected",
disturbance == "high") %>%
pull(culture_ID) %>%
unique()
ID_unconnected_L_high = ds_ecosystems %>%
filter(ecosystem_type == "Large unconnected",
disturbance == "high") %>%
pull(culture_ID) %>%
unique()
# --- Find combinations of ecosystems to create unconnected meta-ecosystems --- #
combinations_S_and_L_low = crossing(ID_unconnected_S_low,
ID_unconnected_L_low) %>%
mutate(disturbance = "low",
metaecosystem_type = "Small-Large",
connection = "unconnected") %>%
rename(ID_first_ecosystem = ID_unconnected_S_low,
ID_second_ecosystem = ID_unconnected_L_low) %>%
select(disturbance,
metaecosystem_type,
connection,
ID_first_ecosystem,
ID_second_ecosystem)
combinations_S_and_L_high = crossing(ID_unconnected_S_high,
ID_unconnected_L_high) %>%
mutate(disturbance = "high",
metaecosystem_type = "Small-Large",
connection = "unconnected") %>%
rename(ID_first_ecosystem = ID_unconnected_S_high,
ID_second_ecosystem = ID_unconnected_L_high) %>%
select(disturbance,
metaecosystem_type,
connection,
ID_first_ecosystem,
ID_second_ecosystem)
combinations_M_and_M_low = combinat::combn(ID_unconnected_M_low,
m = 2) %>%
t() %>%
as.data.frame() %>%
rename(ID_first_ecosystem = V1,
ID_second_ecosystem = V2) %>%
mutate(disturbance = "low",
metaecosystem_type = "Medium-Medium",
connection = "unconnected") %>%
select(disturbance,
metaecosystem_type,
connection,
ID_first_ecosystem,
ID_second_ecosystem)
combinations_M_and_M_high = combinat::combn(ID_unconnected_M_high,
m = 2) %>%
t() %>%
as.data.frame() %>%
rename(ID_first_ecosystem = V1,
ID_second_ecosystem = V2) %>%
mutate(disturbance = "high",
metaecosystem_type = "Medium-Medium",
connection = "unconnected") %>%
select(disturbance,
metaecosystem_type,
connection,
ID_first_ecosystem,
ID_second_ecosystem)
# --- Bind ecosystem combinations --- #
combinations_unconnected_metaeco = rbind(combinations_S_and_L_low,
combinations_S_and_L_high,
combinations_M_and_M_low,
combinations_M_and_M_high) %>%
mutate(system_nr = 1001:(1000 + nrow(.))) %>%
select(system_nr,
disturbance,
metaecosystem_type,
connection,
ID_first_ecosystem,
ID_second_ecosystem)
# --- Find combinations of ecosystems to create connected meta-ecosystems --- #
combinations_connected_metaeco = ds_ecosystems %>%
filter(time_point == 0,
metaecosystem == "yes") %>%
select(system_nr,
disturbance,
metaecosystem_type,
culture_ID) %>%
group_by(system_nr,
disturbance,
metaecosystem_type) %>%
summarise(ID_first_ecosystem = (mean(culture_ID) - 0.5),
ID_second_ecosystem = (mean(culture_ID) + 0.5)) %>%
mutate(connection = "connected") %>%
as.data.frame()
# --- Bind combinations of ecosystems to create unconnected and connected meta-ecosystems --- #
ecosystem_combinations = rbind(combinations_unconnected_metaeco,
combinations_connected_metaeco) %>%
mutate(ecosystems_combined = paste0(ID_first_ecosystem, "|", ID_second_ecosystem))
n_ecosystems_combinations = nrow(ecosystem_combinations)
# --- Create sets for SL unconnected, where in each set a small and a large ecosystems are paired differently --- #
#I keep the small ecosystems on the same order and perform permutations on large ecosystems
SL_unconnected_sys_sets <- vector("list",
length(disturbance_levels))
for (disturbance_i in 1:length(disturbance_levels)) {
ID_small_ecosystems = ds_ecosystems %>%
filter(disturbance == disturbance_levels[disturbance_i],
ecosystem_type == "Small unconnected") %>%
pull(culture_ID) %>%
unique()
ID_large_ecosystems = ds_ecosystems %>%
filter(disturbance == disturbance_levels[disturbance_i],
ecosystem_type == "Large unconnected") %>%
pull(culture_ID) %>%
unique()
#Force small and large ecosystems vectors to have the same length
length_difference <- length(ID_small_ecosystems) - length(ID_large_ecosystems)
if (length_difference > 0) {
ID_large_ecosystems = c(ID_large_ecosystems,
rep("Patch taken off",
times = abs(length(ID_small_ecosystems) -
length(ID_large_ecosystems))))
} else if (length_difference < 0) {
ID_small_ecosystems = c(ID_small_ecosystems,
rep("Patch taken off",
times = abs(length(ID_large_ecosystems) -
length(ID_small_ecosystems))))
}
# Create dataframe
permutations_large = permn(ID_large_ecosystems)
SL_unconnected_sys_sets[[disturbance_i]] = data.frame(disturbance = disturbance_levels[disturbance_i],
metaecosystem_type = "Small-Large",
connection = "unconnected",
ID_first_ecosystem = rep(ID_small_ecosystems, times = length(permutations_large)),
ID_second_ecosystem = unlist(permutations_large),
set = rep(1 : length(permutations_large),
each = length(ID_small_ecosystems)))
expect_equal(nrow(SL_unconnected_sys_sets[[disturbance_i]]),
length(ID_small_ecosystems) * length(permutations_large))
SL_unconnected_sys_sets[[disturbance_i]] = SL_unconnected_sys_sets[[disturbance_i]] %>%
filter(!ID_first_ecosystem == "Patch taken off",
!ID_second_ecosystem == "Patch taken off") %>%
mutate(ID_first_ecosystem = as.double(ID_first_ecosystem),
ID_second_ecosystem = as.double(ID_second_ecosystem)) %>%
full_join(ecosystem_combinations %>%
filter(disturbance == disturbance_levels[disturbance_i],
metaecosystem_type == "Small-Large",
connection == "unconnected")) #Add system_nr & ecosystems_combined
}
SL_unconnected_sys_sets_before_binding = SL_unconnected_sys_sets
SL_unconnected_sys_sets = SL_unconnected_sys_sets %>%
bind_rows()
expect_equal(nrow(SL_unconnected_sys_sets),
nrow(SL_unconnected_sys_sets_before_binding[[1]]) + nrow(SL_unconnected_sys_sets_before_binding[[2]]))
expect_equal(length(SL_unconnected_sys_sets %>%
pull(system_nr) %>%
unique()),
length(ecosystem_combinations %>%
filter(metaecosystem_type == "Small-Large",
connection == "unconnected") %>%
pull(system_nr) %>%
unique()))
# --- Create sets for MM unconnected, where in each set two different medium ecosystems are paired--- #
#To do so, I ...
#Initialise MM_unconnected_sets. Assign 10^4 rows to each matrix so that we have enough rows not to run out of them when we try to assign values to them. Assign 4 columns which will include culture_ID of the first system, second culture_ID of the fist system, culture_ID of the second system, and second culture_ID of the second system.
MM_unconnected_sets = NULL
for(disturbance_i in 1:length(disturbance_levels)){
MM_unconnected_sets[[disturbance_i]] <- matrix(nrow = 10 ^ 4,
ncol = 4)
}
for (disturbance_i in 1:length(disturbance_levels)) {
ID_medium_ecosystems = ds_ecosystems %>%
filter(disturbance == disturbance_levels[disturbance_i],
ecosystem_type == "Medium unconnected") %>%
pull(culture_ID) %>%
unique()
MM_unconnected_systems = combn(ID_medium_ecosystems,
2) %>%
t()
matrix_row = 0
for (first_system_i in 1:nrow(MM_unconnected_systems)) {
#Find culture IDs of the first system (what's the first system?)
first_system = MM_unconnected_systems[first_system_i, ]
for (second_system_i in 1:nrow(MM_unconnected_systems)) {
#Find culture IDs of the second system (what's the second system?)
second_system = MM_unconnected_systems[second_system_i, ]
shared_elements_among_systems = intersect(first_system,
second_system)
if (length(shared_elements_among_systems) == 0) {
matrix_row = matrix_row + 1
#Make first and second system into a set
MM_unconnected_sets[[disturbance_i]][matrix_row,] = c(first_system,
second_system)
print(MM_unconnected_sets[[disturbance_i]][matrix_row,])
}
}
}
#Tidy the dataset with all the ecosystem combinations
MM_unconnected_sets[[disturbance_i]] = MM_unconnected_sets[[disturbance_i]] %>%
as.data.frame() %>%
drop_na()
expect_equal(MM_unconnected_sets[[disturbance_i]] %>%
filter(V1 == V2 | V1 == V3 | V1 == V4 | V2 == V3 | V2 == V4 | V3 == V4) %>%
nrow(),
0)
#Reorder the dataset with all the ecosystem combinations
MM_unconnected_sets_reordered = data.frame(ID_first_ecosystem = NA,
ID_second_ecosystem = NA,
set = NA)
for (set_input in 1:nrow(MM_unconnected_sets[[disturbance_i]])) {
MM_unconnected_sets_reordered = MM_unconnected_sets_reordered %>%
add_row(ID_first_ecosystem = MM_unconnected_sets[[disturbance_i]][set_input, 1],
ID_second_ecosystem = MM_unconnected_sets[[disturbance_i]][set_input, 2],
set = set_input) %>%
add_row(ID_first_ecosystem = MM_unconnected_sets[[disturbance_i]][set_input, 3],
ID_second_ecosystem = MM_unconnected_sets[[disturbance_i]][set_input, 4],
set = set_input)
}
#Add to a list
MM_unconnected_sets[[disturbance_i]] = MM_unconnected_sets_reordered %>%
drop_na() %>%
mutate(disturbance = disturbance_levels[disturbance_i],
metaecosystem_type = "Medium-Medium",
connection = "unconnected")
#Add system nr
ID_combinations_MM_unconnected = ecosystem_combinations %>%
filter(disturbance == disturbance_levels[disturbance_i],
metaecosystem_type == "Medium-Medium",
connection == "unconnected")
MM_unconnected_sets[[disturbance_i]] = full_join(MM_unconnected_sets[[disturbance_i]],
ID_combinations_MM_unconnected)
}
## [1] 6 7 8 9
## [1] 6 7 8 10
## [1] 6 7 9 10
## [1] 6 8 7 9
## [1] 6 8 7 10
## [1] 6 8 9 10
## [1] 6 9 7 8
## [1] 6 9 7 10
## [1] 6 9 8 10
## [1] 6 10 7 8
## [1] 6 10 7 9
## [1] 6 10 8 9
## [1] 7 8 6 9
## [1] 7 8 6 10
## [1] 7 8 9 10
## [1] 7 9 6 8
## [1] 7 9 6 10
## [1] 7 9 8 10
## [1] 7 10 6 8
## [1] 7 10 6 9
## [1] 7 10 8 9
## [1] 8 9 6 7
## [1] 8 9 6 10
## [1] 8 9 7 10
## [1] 8 10 6 7
## [1] 8 10 6 9
## [1] 8 10 7 9
## [1] 9 10 6 7
## [1] 9 10 6 8
## [1] 9 10 7 8
## [1] 61 62 63 64
## [1] 61 62 63 65
## [1] 61 62 64 65
## [1] 61 63 62 64
## [1] 61 63 62 65
## [1] 61 63 64 65
## [1] 61 64 62 63
## [1] 61 64 62 65
## [1] 61 64 63 65
## [1] 61 65 62 63
## [1] 61 65 62 64
## [1] 61 65 63 64
## [1] 62 63 61 64
## [1] 62 63 61 65
## [1] 62 63 64 65
## [1] 62 64 61 63
## [1] 62 64 61 65
## [1] 62 64 63 65
## [1] 62 65 61 63
## [1] 62 65 61 64
## [1] 62 65 63 64
## [1] 63 64 61 62
## [1] 63 64 61 65
## [1] 63 64 62 65
## [1] 63 65 61 62
## [1] 63 65 61 64
## [1] 63 65 62 64
## [1] 64 65 61 62
## [1] 64 65 61 63
## [1] 64 65 62 63
#Bind all sets of MM unconnected
MM_unconnected_sets = MM_unconnected_sets %>%
bind_rows()
expect_equal(length(MM_unconnected_sets %>%
pull(system_nr) %>%
unique()),
length(ecosystem_combinations %>%
filter(metaecosystem_type == "Medium-Medium",
connection == "unconnected") %>%
pull(system_nr) %>%
unique()))
# --- Bind SL and MM unconnected systems --- #
unconnected_combinations_sets = rbind(SL_unconnected_sys_sets,
MM_unconnected_sets) %>%
select(disturbance,
metaecosystem_type,
connection,
set,
system_nr,
ID_first_ecosystem,
ID_second_ecosystem)
Each row is a meta-ecosystem.
It contains also “fake” meta-ecosystems which I created from
unconnected ecosystems
(metaecosystem type = Small-Large unconnected &
metaecosystem type = Medium-Medium unconnected).
Warning appear after the following code, as:
# --- Compute meta-ecosystems for each time point --- #
ds_metaecosystems = NULL
row_i = 0
for (combination_i in 1:n_ecosystems_combinations) {
for (time_point_selected in time_points) {
row_i = row_i + 1
current_day = sampling_days[time_point_selected + 1]
current_system_nr = ecosystem_combinations[combination_i, ]$system_nr
current_combination = ecosystem_combinations[combination_i, ]$ecosystems_combined
current_disturbance = ecosystem_combinations[combination_i, ]$disturbance
current_metaeco_type = ecosystem_combinations[combination_i, ]$metaecosystem_type
current_connection = ecosystem_combinations[combination_i, ]$connection
current_IDs = c(ecosystem_combinations[combination_i, ]$ID_first_ecosystem,
ecosystem_combinations[combination_i, ]$ID_second_ecosystem)
if (current_system_nr %in% metaecosystems_to_take_off)
next
if (current_IDs[1] == current_IDs[2])
next
species_vector_two_ecosystems = ds_ecosystems %>%
filter(time_point == time_point_selected,
culture_ID %in% current_IDs) %>%
ungroup() %>%
select(all_of(protist_species_indiv_per_ml))
absence_presence_two_ecosystems <-
ifelse(species_vector_two_ecosystems > 0, 1, 0)
#Alpha diversity: Shannon (mean between the two ecosystems)
shannon_ecosystem_1 = diversity(species_vector_two_ecosystems[1, ], index = "shannon")
shannon_ecosystem_2 = diversity(species_vector_two_ecosystems[2, ], index = "shannon")
shannon_value = (shannon_ecosystem_1 + shannon_ecosystem_2) / 2
#Alpha diversity: Species richness (mean between the two ecosystems)
richness_ecosystem_1 = specnumber(species_vector_two_ecosystems[1, ])
richness_ecosystem_2 = specnumber(species_vector_two_ecosystems[2, ])
mean_richness_value = (richness_ecosystem_1 + richness_ecosystem_2) / 2
#Beta diversity: Jaccard
jaccard_index_value = vegdist(species_vector_two_ecosystems,
method = "jaccard") %>%
as.numeric()
#Beta diversity: Bray Curtis
bray_curtis_value = vegdist(species_vector_two_ecosystems,
method = "bray") %>%
as.numeric()
#Beta diversity: partitioning of beta diversity from Sorensen index into turnover (Simpson pair-wise dissimilarity) and nestedness (nestedness-fraction of Sorensen)
betapart_core_object = betapart.core(absence_presence_two_ecosystems)
beta_spatial_turnover_value = beta.pair(betapart_core_object)$beta.sim %>% as.double()
beta_nestedness_value = beta.pair(betapart_core_object)$beta.sne %>% as.double()
beta_total_value = beta.pair(betapart_core_object)$beta.sor %>% as.double()
#Gamma diversity: Meta-ecosystem richness
metaecosystem_richness_value = colSums(species_vector_two_ecosystems) %>%
specnumber()
#Put everything together
ds_metaecosystems[[row_i]] = ds_ecosystems %>%
filter(culture_ID %in% current_IDs,
time_point == time_point_selected) %>%
summarise(total_metaecosystem_bioarea_mm2 = sum(bioarea_tot_mm2),
total_metaecosystem_Ble_indiv = sum(Ble_tot_indiv),
total_metaecosystem_Cep_indiv = sum(Cep_tot_indiv),
total_metaecosystem_Col_indiv = sum(Col_tot_indiv),
total_metaecosystem_Eug_indiv = sum(Eug_tot_indiv),
total_metaecosystem_Eup_indiv = sum(Eup_tot_indiv),
total_metaecosystem_Lox_indiv = sum(Lox_tot_indiv),
total_metaecosystem_Pau_indiv = sum(Pau_tot_indiv),
total_metaecosystem_Pca_indiv = sum(Pca_tot_indiv),
total_metaecosystem_Spi_indiv = sum(Spi_tot_indiv),
total_metaecosystem_Spi_te_indiv = sum(Spi_te_tot_indiv),
total_metaecosystem_Tet_indiv = sum(Tet_tot_indiv),
total_water_addition_ml = sum(water_addition_ml)) %>%
mutate(system_nr = current_system_nr,
ecosystems_combined = current_combination,
metaecosystem_type = current_metaeco_type,
ecosystem_size_symmetry = case_when(metaecosystem_type == "Small-Large" ~ "asymmetric",
metaecosystem_type == "Medium-Medium" ~ "symmetric",
metaecosystem_type == "Small-Small" ~ "symmetric",
metaecosystem_type == "Large-Large" ~ "symmetric"),
connection = current_connection,
disturbance = current_disturbance,
time_point = time_point_selected,
day = current_day,
jaccard_index = jaccard_index_value,
bray_curtis = bray_curtis_value,
beta_spatial_turnover = beta_spatial_turnover_value,
beta_nestedness = beta_nestedness_value,
beta_total = beta_total_value,
metaecosystem_richness = metaecosystem_richness_value,
mean_shannon = shannon_value,
mean_richness = mean_richness_value) %>%
ungroup()
}
}
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): missing
## values in results
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): missing
## values in results
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): missing
## values in results
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): missing
## values in results
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
## Warning in vegdist(species_vector_two_ecosystems, method = "jaccard"): you have empty rows: their dissimilarities may be
## meaningless in method "jaccard"
## Warning in vegdist(species_vector_two_ecosystems, method = "bray"): you have empty rows: their dissimilarities may be
## meaningless in method "bray"
ds_metaecosystems = ds_metaecosystems %>%
bind_rows() %>%
as.data.frame() %>%
select(time_point,
day,
system_nr,
ecosystems_combined,
disturbance,
metaecosystem_type,
ecosystem_size_symmetry,
connection,
mean_shannon,
mean_richness,
jaccard_index,
bray_curtis,
beta_spatial_turnover,
beta_nestedness,
beta_total,
metaecosystem_richness,
total_metaecosystem_bioarea_mm2,
paste0("total_metaecosystem_", protist_species, "_indiv"),
total_water_addition_ml)
expect_equal(nrow(ds_metaecosystems),
n_time_points * n_ecosystems_combinations)
Here I’m filtering ecosystems to have only the ones with disturbance high.
ds_ecosystems_both_disturbances = ds_ecosystems
ds_metaecosystems_both_disturbances = ds_metaecosystems
#Filter data sets according to the global disturbance
ds_individuals = ds_individuals %>%
filter(disturbance == disturbance_global_selected)
ds_ecosystems = ds_ecosystems %>%
filter(disturbance == disturbance_global_selected)
ds_ecosystems_effect_size = ds_ecosystems_effect_size %>%
filter(disturbance == disturbance_global_selected)
ds_metaecosystems = ds_metaecosystems %>%
filter(disturbance == disturbance_global_selected)
ds_classes = ds_classes %>%
filter(disturbance == disturbance_global_selected)
ds_classes_effect_size = ds_classes_effect_size %>%
filter(disturbance == disturbance_global_selected)
metaecosystem_type_selected = c("Small-Small",
"Large-Large",
"Medium-Medium",
"Small-Large")
connection_selected = c("connected",
"unconnected")
response_variable_selected = "mean_shannon"
Here we want to look at how this meta-ecosystem variable changed across time by plotting its mean ± 95 confidence interval:
plot.metaecos.points(ds_metaecosystems,
metaecosystem_type_selected,
connection_selected,
response_variable_selected)
plot.metaecos.replicates(ds_metaecosystems,
metaecosystem_type_selected,
response_variable_selected)
response_variable_selected = "bray_curtis"
Here we want to look at how this meta-ecosystem variable changed across time by plotting its mean ± 95 confidence interval:
plot.metaecos.points(ds_metaecosystems,
metaecosystem_type_selected,
connection_selected,
response_variable_selected)
plot.metaecos.replicates(ds_metaecosystems,
metaecosystem_type_selected,
response_variable_selected)
## Warning: Removed 2 rows containing non-finite outside the scale range
## (`stat_summary()`).
response_variable_selected = "metaecosystem_richness"
Here we want to look at how this meta-ecosystem variable changed across time by plotting its mean ± 95 confidence interval:
plot.metaecos.points(ds_metaecosystems,
metaecosystem_type_selected,
connection_selected,
response_variable_selected)
plot.metaecos.replicates(ds_metaecosystems,
metaecosystem_type_selected,
response_variable_selected)
response_variable_selected = "total_metaecosystem_bioarea_mm2"
Here we want to look at how this meta-ecosystem variable changed across time by plotting its mean ± 95 confidence interval:
plot.metaecos.points(ds_metaecosystems,
metaecosystem_type_selected,
connection_selected,
response_variable_selected)
plot.metaecos.replicates(ds_metaecosystems,
metaecosystem_type_selected,
response_variable_selected)
response_variable_selected = "mean_shannon"
metaecosystem_type_selected = c("Medium-Medium",
"Small-Large")
Here we want to look at how this meta-ecosystem variable changed across time by plotting its mean ± 95 confidence interval:
plot.metaecos.points(ds_metaecosystems,
metaecosystem_type_selected,
connection_selected,
response_variable_selected)
plot.metaecos.replicates(ds_metaecosystems,
metaecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among meta-ecosystems. To make it easier to interpret differences, we decided to construct a model for each comparisons we are interested in, which are: SL (connected vs unconnected) and MM (connected vs unconnected).
comparison_type = "all"
metaecosystem_type_selected = c("Small-Large")
Our first step in the data analysis involves filtering the data to isolate the relevant data. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure we filtered data the right way.
# --- FILTER DATA --- #
filtered_data = ds_metaecosystems %>%
filter(time_point %in% time_points_model,
metaecosystem_type %in% metaecosystem_type_selected,
!is.na(!!sym("total_water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.metaecos.points(filtered_data,
metaecosystem_type_selected,
connection_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same meta-ecosystem on multiple occasions, we can develop mixed effect models to examine how the connection influenced this meta-ecosystem variable. To study the effects of connection we compare two models to a null model using ANOVA: a full model and a reduced model. In all models, we treat system nr as having a random effect on how the slope and intercept of the relationship between response variable and time, with the slope and intercept being correlated (Bates et al. 2015). We also include the total water that was added due to evaporation in the microwave and the time point before the first disturbance (baseline). In the syntax of lmer4 the three models look this this:
Full model = response_variable ~connection * scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Reduced model = response_variable ~connection + scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Null model = response_variable ~scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Unconnected meta-ecosystems are made of paired unconnected
ecosystems, which are paired randomly. However, how to pair unconnected
ecosystems can be done in multiple ways, as unconnected ecosystems did
not interact and therefore any combination between ecosystems would be
arbitrary. To make sure that the random combination we selected did not
bias our results, we run all the possible combinations of ecosystems
constituting unconnected meta-ecosystems. The ecosystem combinations are
into the objects unconnected_combinations_sets (Data >
Meta-ecosystems). We therefore compute a p-value for each unconnected
ecosystems combination, creating a p-value distribution. We keep as
p-value of the comparison the median of such distributions.
# --- ADD BASELINES --- #
baselines = ds_metaecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(system_nr,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- PREPARE TO COMPARE FULL, REDUCED, AND NULL MODEL WHILE RESHUFFLING ECOSYSTEM COMBINATIONS --- #
unconnected_combinations_sets_filtered = unconnected_combinations_sets %>%
filter(disturbance == disturbance_global_selected,
metaecosystem_type %in% metaecosystem_type_selected)
n_sets = unconnected_combinations_sets_filtered %>%
pull(set) %>%
max()
iterated_results_table = data.frame(Response = as.character(NA),
Levels = as.character(NA),
ΔAIC_full = NA,
p_full = NA,
ΔR2_full = NA,
ΔAIC_fix = NA,
p_fix = NA,
ΔR2_fix = NA,
combination_set = NA,
system_nr_unconnected_systems = as.character(NA)) %>%
slice(-1)
# --- COMPARE FULL, REDUCED, AND NULL MODEL WHILE RESHUFFLING ECOSYSTEM COMBINATIONS --- #
for (set_i in 1:n_sets) {
# Filter the data to contain all the connected meta-ecosystems and only a subset of unconnected meta-ecosystems
system_nr_unconnected_systems_selected = unconnected_combinations_sets_filtered %>%
filter(metaecosystem_type %in% metaecosystem_type_selected,
connection == "unconnected",
set == set_i) %>%
pull(system_nr)
filtered_data_2 = filtered_data %>%
filter(connection == "connected" |
(connection == "unconnected" &
system_nr %in% system_nr_unconnected_systems_selected))
# Construct models
full_model = try.different.optimizer.full.model()
reduced_model = try.different.optimizer.reduced.model()
null_model = try.different.optimizer.null.model()
# If all the optimisers fail, move on to the next iteration
if (is.null(full_model) || is.null(reduced_model) || is.null(null_model)) {
cat("This model could not be fitted with any optimiser. The unconnected meta-ecosystems in this iteration were:",
system_nr_unconnected_systems_selected,
"\n")
next
}
if(plot_model_residuals_metaecos == TRUE){
# Plot residuals - full model
print(qqnorm(resid(full_model))); print(qqline(resid(full_model)))
#full_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, full_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(full_model),
residuals = resid(full_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_full_model.png")),
plot = plot,
width = 8,
height = 6)
# Plot residuals - reduced model
print(qqnorm(resid(reduced_model))); print(qqline(resid(reduced_model)))
#reduced_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, reduced_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(reduced_model),
residuals = resid(reduced_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_reduced_model.png")),
plot = plot,
width = 8,
height = 6)
# Plot residuals - null model
print(qqnorm(resid(null_model))); print(qqline(resid(null_model)))
#null_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, null_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(null_model),
residuals = resid(null_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_null_model.png")),
plot = plot,
width = 8,
height = 6)
}
# Give model statistics
model_stats_full = compute.model.stats(full_model,
null_model,
"mixed_model")
model_stats_reduced = compute.model.stats(reduced_model,
null_model,
"mixed_model")
# Save model statistics
iterated_results_table = fill.results.table(iterated_results_table,
response_variable_selected,
metaecosystem_type_selected,
model_stats_full,
model_stats_reduced)
iterated_results_table$set[nrow(iterated_results_table)] = set_i
iterated_results_table$system_nr_unconnected_systems[nrow(iterated_results_table)] =
paste(system_nr_unconnected_systems_selected, collapse = " ")
}
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: nlminbwrap "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: optimx (L-BFGS-B)"
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: optimx (L-BFGS-B)"
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: optimx (L-BFGS-B)"
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
Full vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
data.frame(deltaAIC = median(iterated_results_table$ΔAIC_full),
p_value = median(iterated_results_table$p_full),
R2 = NA) %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -3.5 0.024 ** moderate
# --- FULL VS NULL MODEL - SHOW ΔAIC & P VALUE DISTRIBUTIONS --- #
hist(iterated_results_table$ΔAIC_full, main = "Distribution of ΔAIC of the full model.")
hist(iterated_results_table$p_full, main = "Distribution of p-values of the full model.")
# --- FULL VS NULL MODEL - SHOW WHICH UNCONNECTED META-ECOSYSTEM NUMBER PRODUCD WHICH AIC --- #
iterated_results_table %>%
select(system_nr_unconnected_systems,
ΔAIC_full) %>%
arrange(ΔAIC_full)
## system_nr_unconnected_systems ΔAIC_full
## 1 1030 1033 1039 1041 -7.51306732
## 2 1030 1032 1039 1041 -7.02345583
## 3 1029 1033 1040 1041 -6.76872644
## 4 1030 1032 1036 1044 -6.69233707
## 5 1030 1031 1038 1044 -6.66913982
## 6 1028 1035 1039 1041 -6.66814014
## 7 1030 1034 1038 1041 -6.64329963
## 8 1030 1033 1036 1044 -6.57942276
## 9 1029 1035 1038 1041 -6.42915976
## 10 1028 1035 1036 1044 -6.36362618
## 11 1026 1032 1039 1045 -6.33918461
## 12 1029 1032 1036 1045 -6.31038927
## 13 1027 1035 1039 1041 -6.29214851
## 14 1026 1035 1038 1044 -6.18810738
## 15 1028 1031 1040 1044 -6.13658713
## 16 1027 1035 1036 1044 -6.05590587
## 17 1027 1031 1039 1045 -6.04944237
## 18 1029 1032 1040 1041 -6.00714008
## 19 1028 1034 1040 1041 -5.96367365
## 20 1028 1031 1039 1045 -5.94141173
## 21 1029 1031 1038 1045 -5.92906253
## 22 1026 1033 1040 1044 -5.86314850
## 23 1026 1032 1040 1044 -5.83616698
## 24 1027 1031 1040 1044 -5.79545644
## 25 1028 1034 1036 1045 -5.77607641
## 26 1030 1031 1037 1044 -5.67071157
## 27 1029 1033 1036 1045 -5.59033566
## 28 1026 1034 1038 1045 -5.58737717
## 29 1027 1034 1036 1045 -5.55714167
## 30 1026 1035 1037 1044 -5.53867304
## 31 1029 1035 1037 1041 -5.45283781
## 32 1026 1033 1039 1045 -5.39065154
## 33 1030 1031 1039 1043 -5.35971884
## 34 1027 1034 1040 1041 -5.35791984
## 35 1029 1031 1037 1045 -5.20600114
## 36 1029 1031 1040 1043 -5.15029459
## 37 1030 1034 1036 1043 -5.02010648
## 38 1030 1034 1037 1041 -5.01173563
## 39 1029 1035 1036 1043 -4.91270656
## 40 1026 1035 1039 1043 -4.85330031
## 41 1026 1034 1037 1045 -4.81740199
## 42 1026 1034 1040 1043 -4.68334153
## 43 1028 1032 1039 1041 -4.45838701
## 44 1028 1032 1036 1044 -4.41758084
## 45 1030 1032 1038 1041 -4.27659935
## 46 1027 1031 1038 1044 -4.19206686
## 47 1026 1032 1038 1044 -4.15666116
## 48 1030 1032 1038 1044 -4.14110470
## 49 1029 1032 1038 1041 -4.07772739
## 50 1028 1031 1037 1044 -4.03937298
## 51 1027 1031 1039 1043 -3.85922136
## 52 1028 1032 1036 1045 -3.84798012
## 53 1027 1031 1038 1045 -3.84438425
## 54 1026 1032 1038 1045 -3.73214830
## 55 1029 1032 1038 1045 -3.64851804
## 56 1027 1034 1038 1041 -3.62378098
## 57 1027 1035 1038 1044 -3.55398145
## 58 1027 1035 1038 1041 -3.54303014
## 59 1028 1034 1037 1041 -3.51764143
## 60 1030 1031 1039 1042 -3.49558386
## 61 1026 1032 1039 1043 -3.49376288
## 62 1028 1032 1039 1045 -3.47880613
## 63 1027 1031 1040 1043 -3.47568611
## 64 1027 1034 1038 1045 -3.47008490
## 65 1029 1031 1037 1043 -3.46812601
## 66 1028 1031 1037 1045 -3.46338047
## 67 1027 1033 1039 1041 -3.42800385
## 68 1028 1032 1040 1041 -3.35654314
## 69 1029 1032 1036 1043 -3.34572010
## 70 1029 1033 1037 1041 -3.33202262
## 71 1028 1035 1037 1041 -3.31021110
## 72 1026 1035 1039 1042 -3.26260282
## 73 1029 1031 1040 1042 -3.24979460
## 74 1027 1034 1036 1043 -3.23917817
## 75 1028 1035 1037 1044 -3.21856176
## 76 1030 1031 1037 1043 -3.19176971
## 77 1026 1033 1037 1044 -3.18160065
## 78 1029 1035 1036 1042 -3.15557672
## 79 1030 1034 1036 1042 -3.12214234
## 80 1030 1032 1036 1043 -3.08229395
## 81 1027 1033 1036 1044 -3.08021772
## 82 1028 1032 1040 1044 -3.07970403
## 83 1026 1034 1040 1042 -3.04364678
## 84 1026 1034 1037 1043 -3.02991265
## 85 1027 1035 1036 1043 -2.99908310
## 86 1028 1034 1037 1045 -2.99641806
## 87 1030 1032 1039 1043 -2.88232807
## 88 1026 1032 1040 1043 -2.86091205
## 89 1027 1034 1040 1043 -2.81667367
## 90 1027 1035 1039 1043 -2.77248860
## 91 1026 1035 1037 1043 -2.71011153
## 92 1030 1033 1037 1041 -2.70249648
## 93 1029 1032 1040 1043 -2.61494825
## 94 1030 1034 1037 1043 -2.48957061
## 95 1027 1033 1040 1041 -2.46648463
## 96 1029 1035 1037 1043 -2.37425322
## 97 1026 1033 1037 1045 -2.25810406
## 98 1030 1033 1037 1044 -2.19789389
## 99 1029 1031 1038 1042 -2.18357997
## 100 1027 1033 1036 1045 -2.17122704
## 101 1028 1031 1039 1042 -2.09311177
## 102 1029 1033 1037 1045 -1.94237775
## 103 1026 1034 1038 1042 -1.92165879
## 104 1030 1031 1038 1042 -1.91011317
## 105 1028 1034 1036 1042 -1.82896298
## 106 1027 1033 1039 1045 -1.76079567
## 107 1027 1033 1040 1044 -1.74910621
## 108 1026 1035 1038 1042 -1.64216226
## 109 1030 1034 1038 1042 -1.52196732
## 110 1029 1035 1038 1042 -1.49447493
## 111 1028 1031 1040 1042 -1.47190481
## 112 1028 1035 1036 1042 -1.30127605
## 113 1028 1035 1039 1042 -1.20358413
## 114 1026 1033 1039 1042 -1.19593058
## 115 1028 1034 1040 1042 -1.15934065
## 116 1029 1033 1036 1042 -1.15136955
## 117 1030 1033 1036 1042 -0.55586010
## 118 1026 1033 1040 1042 -0.38708230
## 119 1030 1033 1039 1042 -0.23884778
## 120 1029 1033 1040 1042 -0.00128363
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
data.frame(deltaAIC = median(iterated_results_table$ΔAIC_fix),
p_value = median(iterated_results_table$p_fix),
R2 = NA) %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -3 0.025 ** moderate
# --- REDUCED VS NULL MODEL - SHOW ΔAIC & P VALUE --- #
hist(iterated_results_table$ΔAIC_fix, main = "Distribution of ΔAIC of the reduced model.")
hist(iterated_results_table$p_fix, main = "Distribution of p-values of the reduced model.")
# --- REDUCED VS NULL MODEL - SHOW WHICH UNCONNECTED META-ECOSYSTEM NUMBER PRODUCD WHICH AIC --- #
iterated_results_table %>%
select(system_nr_unconnected_systems,
ΔAIC_fix) %>%
arrange(ΔAIC_fix)
## system_nr_unconnected_systems ΔAIC_fix
## 1 1030 1032 1039 1041 -6.5242021
## 2 1030 1032 1036 1044 -6.4019885
## 3 1029 1032 1036 1045 -6.3687732
## 4 1026 1032 1039 1045 -6.3525979
## 5 1029 1032 1040 1041 -5.9613789
## 6 1026 1032 1040 1044 -5.7931178
## 7 1027 1031 1039 1045 -5.6947303
## 8 1027 1035 1039 1041 -5.5813867
## 9 1027 1035 1036 1044 -5.4356780
## 10 1027 1031 1040 1044 -5.4322640
## 11 1027 1034 1036 1045 -5.2989743
## 12 1030 1032 1038 1044 -5.1831854
## 13 1028 1032 1036 1044 -5.1782445
## 14 1027 1034 1040 1041 -5.1033867
## 15 1029 1031 1037 1045 -5.0353804
## 16 1030 1031 1037 1044 -4.9664930
## 17 1026 1035 1037 1044 -4.8742274
## 18 1028 1032 1039 1041 -4.8505993
## 19 1028 1032 1036 1045 -4.7899509
## 20 1028 1032 1039 1045 -4.7701995
## 21 1029 1032 1038 1045 -4.7565428
## 22 1029 1035 1037 1041 -4.7005805
## 23 1026 1034 1037 1045 -4.6557222
## 24 1026 1032 1038 1044 -4.6160619
## 25 1030 1032 1038 1041 -4.5698937
## 26 1029 1032 1038 1041 -4.4275810
## 27 1026 1032 1038 1045 -4.3186395
## 28 1030 1034 1037 1041 -4.2925743
## 29 1027 1035 1038 1044 -4.2636070
## 30 1028 1032 1040 1044 -4.2056446
## 31 1027 1034 1038 1045 -4.1597526
## 32 1027 1031 1038 1044 -4.1241449
## 33 1030 1031 1039 1042 -4.1129019
## 34 1028 1031 1037 1044 -4.0131267
## 35 1028 1035 1037 1044 -3.9503864
## 36 1026 1035 1039 1042 -3.8827840
## 37 1027 1031 1038 1045 -3.8820638
## 38 1029 1035 1036 1042 -3.8601392
## 39 1030 1034 1036 1042 -3.8195678
## 40 1028 1034 1037 1045 -3.8185170
## 41 1029 1031 1040 1042 -3.7490284
## 42 1028 1032 1040 1041 -3.7465369
## 43 1028 1031 1037 1045 -3.6774870
## 44 1028 1035 1036 1044 -3.6447318
## 45 1027 1034 1038 1041 -3.6086595
## 46 1027 1035 1038 1041 -3.5751790
## 47 1026 1034 1040 1042 -3.5454923
## 48 1028 1034 1036 1045 -3.4674074
## 49 1028 1034 1037 1041 -3.4658824
## 50 1028 1035 1039 1041 -3.3012734
## 51 1028 1035 1037 1041 -3.3002370
## 52 1028 1031 1039 1045 -3.2822744
## 53 1026 1032 1039 1043 -3.2803192
## 54 1029 1032 1036 1043 -3.1858595
## 55 1027 1033 1036 1044 -3.1409523
## 56 1030 1031 1038 1044 -3.0961568
## 57 1027 1031 1039 1043 -3.0762714
## 58 1026 1035 1038 1044 -3.0625540
## 59 1026 1033 1037 1044 -3.0438501
## 60 1029 1032 1040 1043 -3.0069644
## 61 1030 1032 1039 1043 -2.9949332
## 62 1027 1033 1039 1041 -2.9801485
## 63 1028 1031 1040 1044 -2.9651123
## 64 1028 1031 1039 1042 -2.9624140
## 65 1029 1033 1037 1041 -2.9344810
## 66 1028 1034 1036 1042 -2.8841038
## 67 1029 1031 1038 1045 -2.8441035
## 68 1029 1035 1038 1041 -2.8207573
## 69 1028 1034 1040 1041 -2.8185704
## 70 1026 1034 1038 1045 -2.7913804
## 71 1030 1034 1038 1041 -2.7282355
## 72 1029 1031 1038 1042 -2.7167923
## 73 1030 1034 1038 1042 -2.7071970
## 74 1026 1032 1040 1043 -2.6852767
## 75 1027 1031 1040 1043 -2.6696673
## 76 1027 1034 1040 1043 -2.6645188
## 77 1028 1035 1039 1042 -2.6583152
## 78 1029 1031 1037 1043 -2.6527999
## 79 1029 1035 1038 1042 -2.6507190
## 80 1030 1032 1036 1043 -2.6428388
## 81 1030 1033 1037 1044 -2.6298842
## 82 1029 1033 1037 1045 -2.6055988
## 83 1027 1034 1036 1043 -2.5528894
## 84 1030 1033 1036 1044 -2.5476393
## 85 1030 1031 1038 1042 -2.5157836
## 86 1027 1033 1036 1045 -2.4854642
## 87 1026 1034 1038 1042 -2.4760963
## 88 1027 1033 1039 1045 -2.4693796
## 89 1028 1035 1036 1042 -2.4490379
## 90 1026 1033 1037 1045 -2.4010292
## 91 1028 1034 1040 1042 -2.3965497
## 92 1029 1033 1036 1045 -2.3429375
## 93 1027 1035 1039 1043 -2.3028448
## 94 1029 1033 1036 1042 -2.2793542
## 95 1026 1035 1038 1042 -2.2391077
## 96 1026 1034 1037 1043 -2.2315024
## 97 1030 1033 1039 1041 -2.2139067
## 98 1026 1033 1039 1042 -2.1802141
## 99 1030 1033 1037 1041 -2.1717683
## 100 1027 1033 1040 1044 -2.1663397
## 101 1026 1033 1039 1045 -2.1474372
## 102 1028 1031 1040 1042 -2.0962917
## 103 1030 1031 1037 1043 -1.9920062
## 104 1027 1035 1036 1043 -1.9657672
## 105 1029 1033 1040 1041 -1.9452229
## 106 1026 1033 1040 1044 -1.9271069
## 107 1027 1033 1040 1041 -1.9233137
## 108 1030 1034 1037 1043 -1.7837864
## 109 1030 1033 1036 1042 -1.7534168
## 110 1029 1035 1037 1043 -1.7533827
## 111 1030 1033 1039 1042 -1.7233813
## 112 1026 1035 1037 1043 -1.6317718
## 113 1029 1033 1040 1042 -1.2869543
## 114 1029 1031 1040 1043 -1.2760128
## 115 1026 1033 1040 1042 -1.1577914
## 116 1026 1034 1040 1043 -1.0575825
## 117 1030 1031 1039 1043 -0.9795761
## 118 1026 1035 1039 1043 -0.8007512
## 119 1029 1035 1036 1043 -0.6381440
## 120 1030 1034 1036 1043 -0.5508780
metaecosystem_type_selected = c("Medium-Medium")
Our first step in the data analysis involves filtering the data to isolate the relevant data. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure we filtered data the right way.
# --- FILTER DATA --- #
filtered_data = ds_metaecosystems %>%
filter(time_point %in% time_points_model,
metaecosystem_type %in% metaecosystem_type_selected,
!is.na(!!sym("total_water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.metaecos.points(filtered_data,
metaecosystem_type_selected,
connection_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same meta-ecosystem on multiple occasions, we can develop mixed effect models to examine how the connection influenced this meta-ecosystem variable. To study the effects of connection we compare two models to a null model using ANOVA: a full model and a reduced model. In all models, we treat system nr as having a random effect on how the slope and intercept of the relationship between response variable and time, with the slope and intercept being correlated (Bates et al. 2015). We also include the total water that was added due to evaporation in the microwave and the time point before the first disturbance (baseline). In the syntax of lmer4 the three models look this this:
Full model = response_variable ~connection * scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Reduced model = response_variable ~connection + scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Null model = response_variable ~scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Unconnected meta-ecosystems are made of paired unconnected
ecosystems, which are paired randomly. However, how to pair unconnected
ecosystems can be done in multiple ways, as unconnected ecosystems did
not interact and therefore any combination between ecosystems would be
arbitrary. To make sure that the random combination we selected did not
bias our results, we run all the possible combinations of ecosystems
constituting unconnected meta-ecosystems. The ecosystem combinations are
into the objects unconnected_combinations_sets (Data >
Meta-ecosystems). We therefore compute a p-value for each unconnected
ecosystems combination, creating a p-value distribution. We keep as
p-value of the comparison the median of such distributions.
# --- ADD BASELINES --- #
baselines = ds_metaecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(system_nr,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- PREPARE TO COMPARE FULL, REDUCED, AND NULL MODEL WHILE RESHUFFLING ECOSYSTEM COMBINATIONS --- #
unconnected_combinations_sets_filtered = unconnected_combinations_sets %>%
filter(disturbance == disturbance_global_selected,
metaecosystem_type %in% metaecosystem_type_selected)
n_sets = unconnected_combinations_sets_filtered %>%
pull(set) %>%
max()
iterated_results_table = data.frame(Response = as.character(NA),
Levels = as.character(NA),
ΔAIC_full = NA,
p_full = NA,
ΔR2_full = NA,
ΔAIC_fix = NA,
p_fix = NA,
ΔR2_fix = NA,
combination_set = NA,
system_nr_unconnected_systems = as.character(NA)) %>%
slice(-1)
# --- COMPARE FULL, REDUCED, AND NULL MODEL WHILE RESHUFFLING ECOSYSTEM COMBINATIONS --- #
for (set_i in 1:n_sets) {
# Filter the data to contain all the connected meta-ecosystems and only a subset of unconnected meta-ecosystems
system_nr_unconnected_systems_selected = unconnected_combinations_sets_filtered %>%
filter(metaecosystem_type %in% metaecosystem_type_selected,
connection == "unconnected",
set == set_i) %>%
pull(system_nr)
filtered_data_2 = filtered_data %>%
filter(connection == "connected" |
(connection == "unconnected" &
system_nr %in% system_nr_unconnected_systems_selected))
# Construct models
full_model = try.different.optimizer.full.model()
reduced_model = try.different.optimizer.reduced.model()
null_model = try.different.optimizer.null.model()
# If all the optimisers fail, move on to the next iteration
if (is.null(full_model) || is.null(reduced_model) || is.null(null_model)) {
cat("This model could not be fitted with any optimiser. The unconnected meta-ecosystems in this iteration were:",
system_nr_unconnected_systems_selected,
"\n")
next
}
if(plot_model_residuals_metaecos == TRUE){
# Plot residuals - full model
print(qqnorm(resid(full_model))); print(qqline(resid(full_model)))
#full_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, full_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(full_model),
residuals = resid(full_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_full_model.png")),
plot = plot,
width = 8,
height = 6)
# Plot residuals - reduced model
print(qqnorm(resid(reduced_model))); print(qqline(resid(reduced_model)))
#reduced_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, reduced_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(reduced_model),
residuals = resid(reduced_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_reduced_model.png")),
plot = plot,
width = 8,
height = 6)
# Plot residuals - null model
print(qqnorm(resid(null_model))); print(qqline(resid(null_model)))
#null_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, null_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(null_model),
residuals = resid(null_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_null_model.png")),
plot = plot,
width = 8,
height = 6)
}
# Give model statistics
model_stats_full = compute.model.stats(full_model,
null_model,
"mixed_model")
model_stats_reduced = compute.model.stats(reduced_model,
null_model,
"mixed_model")
# Save model statistics
iterated_results_table = fill.results.table(iterated_results_table,
response_variable_selected,
metaecosystem_type_selected,
model_stats_full,
model_stats_reduced)
iterated_results_table$set[nrow(iterated_results_table)] = set_i
iterated_results_table$system_nr_unconnected_systems[nrow(iterated_results_table)] =
paste(system_nr_unconnected_systems_selected, collapse = " ")
}
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: optimx (L-BFGS-B)"
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: optimx (L-BFGS-B)"
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
Full vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
data.frame(deltaAIC = median(iterated_results_table$ΔAIC_full),
p_value = median(iterated_results_table$p_full),
R2 = NA) %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 2.7 0.511 none
# --- FULL VS NULL MODEL - SHOW ΔAIC & P VALUE DISTRIBUTIONS --- #
hist(iterated_results_table$ΔAIC_full, main = "Distribution of ΔAIC of the full model.")
hist(iterated_results_table$p_full, main = "Distribution of p-values of the full model.")
# --- FULL VS NULL MODEL - SHOW WHICH UNCONNECTED META-ECOSYSTEM NUMBER PRODUCD WHICH AIC --- #
iterated_results_table %>%
select(system_nr_unconnected_systems,
ΔAIC_full) %>%
arrange(ΔAIC_full)
## system_nr_unconnected_systems ΔAIC_full
## 1 1060 1065 -0.3463382
## 2 1065 1060 -0.3463382
## 3 1062 1063 -0.2241152
## 4 1063 1062 -0.2241152
## 5 1061 1064 -0.2240414
## 6 1064 1061 -0.2240414
## 7 1056 1064 0.8730968
## 8 1064 1056 0.8730968
## 9 1057 1062 1.1234938
## 10 1062 1057 1.1234938
## 11 1059 1060 1.5279912
## 12 1060 1059 1.5279912
## 13 1056 1065 2.1939509
## 14 1065 1056 2.1939509
## 15 1059 1061 2.6583865
## 16 1061 1059 2.6583865
## 17 1057 1065 2.9562379
## 18 1065 1057 2.9562379
## 19 1058 1062 3.0355166
## 20 1062 1058 3.0355166
## 21 1059 1063 3.1582663
## 22 1063 1059 3.1582663
## 23 1058 1064 3.3818448
## 24 1064 1058 3.3818448
## 25 1057 1061 3.4222337
## 26 1061 1057 3.4222337
## 27 1056 1063 3.5186732
## 28 1063 1056 3.5186732
## 29 1058 1060 3.6690812
## 30 1060 1058 3.6690812
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
data.frame(deltaAIC = median(iterated_results_table$ΔAIC_fix),
p_value = median(iterated_results_table$p_fix),
R2 = NA) %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 1.9 0.762 none
# --- REDUCED VS NULL MODEL - SHOW ΔAIC & P VALUE --- #
hist(iterated_results_table$ΔAIC_fix, main = "Distribution of ΔAIC of the reduced model.")
hist(iterated_results_table$p_fix, main = "Distribution of p-values of the reduced model.")
# --- REDUCED VS NULL MODEL - SHOW WHICH UNCONNECTED META-ECOSYSTEM NUMBER PRODUCD WHICH AIC --- #
iterated_results_table %>%
select(system_nr_unconnected_systems,
ΔAIC_fix) %>%
arrange(ΔAIC_fix)
## system_nr_unconnected_systems ΔAIC_fix
## 1 1059 1060 1.116388
## 2 1060 1059 1.116388
## 3 1056 1064 1.156444
## 4 1064 1056 1.156444
## 5 1057 1062 1.191835
## 6 1062 1057 1.191835
## 7 1057 1065 1.536992
## 8 1065 1057 1.536992
## 9 1056 1065 1.695270
## 10 1065 1056 1.695270
## 11 1058 1064 1.813361
## 12 1064 1058 1.813361
## 13 1059 1063 1.849348
## 14 1063 1059 1.849348
## 15 1062 1063 1.908041
## 16 1063 1062 1.908041
## 17 1059 1061 1.918391
## 18 1061 1059 1.918391
## 19 1058 1060 1.943163
## 20 1060 1058 1.943163
## 21 1058 1062 1.950498
## 22 1062 1058 1.950498
## 23 1057 1061 1.957239
## 24 1061 1057 1.957239
## 25 1056 1063 1.965224
## 26 1063 1056 1.965224
## 27 1060 1065 1.978036
## 28 1065 1060 1.978036
## 29 1061 1064 1.998788
## 30 1064 1061 1.998788
Following the initial inspection, we proceed to analyse differences among meta-ecosystems. To make it easier to interpret differences, we decided to construct a model for each comparisons we are interested in, which are: SL (connected vs unconnected) and MM (connected vs unconnected).
response_variable_selected = "bray_curtis"
metaecosystem_type_selected = c("Medium-Medium",
"Small-Large")
Here we want to look at how this meta-ecosystem variable changed across time by plotting its mean ± 95 confidence interval:
plot.metaecos.points(ds_metaecosystems,
metaecosystem_type_selected,
connection_selected,
response_variable_selected)
plot.metaecos.replicates(ds_metaecosystems,
metaecosystem_type_selected,
response_variable_selected)
metaecosystem_type_selected = c("Small-Large")
Our first step in the data analysis involves filtering the data to isolate the relevant data. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure we filtered data the right way.
# --- FILTER DATA --- #
filtered_data = ds_metaecosystems %>%
filter(time_point %in% time_points_model,
metaecosystem_type %in% metaecosystem_type_selected,
!is.na(!!sym("total_water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.metaecos.points(filtered_data,
metaecosystem_type_selected,
connection_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same meta-ecosystem on multiple occasions, we can develop mixed effect models to examine how the connection influenced this meta-ecosystem variable. To study the effects of connection we compare two models to a null model using ANOVA: a full model and a reduced model. In all models, we treat system nr as having a random effect on how the slope and intercept of the relationship between response variable and time, with the slope and intercept being correlated (Bates et al. 2015). We also include the total water that was added due to evaporation in the microwave and the time point before the first disturbance (baseline). In the syntax of lmer4 the three models look this this:
Full model = response_variable ~connection * scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Reduced model = response_variable ~connection + scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Null model = response_variable ~scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Unconnected meta-ecosystems are made of paired unconnected
ecosystems, which are paired randomly. However, how to pair unconnected
ecosystems can be done in multiple ways, as unconnected ecosystems did
not interact and therefore any combination between ecosystems would be
arbitrary. To make sure that the random combination we selected did not
bias our results, we run all the possible combinations of ecosystems
constituting unconnected meta-ecosystems. The ecosystem combinations are
into the objects unconnected_combinations_sets (Data >
Meta-ecosystems). We therefore compute a p-value for each unconnected
ecosystems combination, creating a p-value distribution. We keep as
p-value of the comparison the median of such distributions.
# --- ADD BASELINES --- #
baselines = ds_metaecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(system_nr,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- PREPARE TO COMPARE FULL, REDUCED, AND NULL MODEL WHILE RESHUFFLING ECOSYSTEM COMBINATIONS --- #
unconnected_combinations_sets_filtered = unconnected_combinations_sets %>%
filter(disturbance == disturbance_global_selected,
metaecosystem_type %in% metaecosystem_type_selected)
n_sets = unconnected_combinations_sets_filtered %>%
pull(set) %>%
max()
iterated_results_table = data.frame(Response = as.character(NA),
Levels = as.character(NA),
ΔAIC_full = NA,
p_full = NA,
ΔR2_full = NA,
ΔAIC_fix = NA,
p_fix = NA,
ΔR2_fix = NA,
combination_set = NA,
system_nr_unconnected_systems = as.character(NA)) %>%
slice(-1)
# --- COMPARE FULL, REDUCED, AND NULL MODEL WHILE RESHUFFLING ECOSYSTEM COMBINATIONS --- #
for (set_i in 1:n_sets) {
# Filter the data to contain all the connected meta-ecosystems and only a subset of unconnected meta-ecosystems
system_nr_unconnected_systems_selected = unconnected_combinations_sets_filtered %>%
filter(metaecosystem_type %in% metaecosystem_type_selected,
connection == "unconnected",
set == set_i) %>%
pull(system_nr)
filtered_data_2 = filtered_data %>%
filter(connection == "connected" |
(connection == "unconnected" &
system_nr %in% system_nr_unconnected_systems_selected))
# Construct models
full_model = try.different.optimizer.full.model()
reduced_model = try.different.optimizer.reduced.model()
null_model = try.different.optimizer.null.model()
# If all the optimisers fail, move on to the next iteration
if (is.null(full_model) || is.null(reduced_model) || is.null(null_model)) {
cat("This model could not be fitted with any optimiser. The unconnected meta-ecosystems in this iteration were:",
system_nr_unconnected_systems_selected,
"\n")
next
}
if(plot_model_residuals_metaecos == TRUE){
# Plot residuals - full model
print(qqnorm(resid(full_model))); print(qqline(resid(full_model)))
#full_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, full_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(full_model),
residuals = resid(full_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_full_model.png")),
plot = plot,
width = 8,
height = 6)
# Plot residuals - reduced model
print(qqnorm(resid(reduced_model))); print(qqline(resid(reduced_model)))
#reduced_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, reduced_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(reduced_model),
residuals = resid(reduced_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_reduced_model.png")),
plot = plot,
width = 8,
height = 6)
# Plot residuals - null model
print(qqnorm(resid(null_model))); print(qqline(resid(null_model)))
#null_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, null_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(null_model),
residuals = resid(null_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_null_model.png")),
plot = plot,
width = 8,
height = 6)
}
# Give model statistics
model_stats_full = compute.model.stats(full_model,
null_model,
"mixed_model")
model_stats_reduced = compute.model.stats(reduced_model,
null_model,
"mixed_model")
# Save model statistics
iterated_results_table = fill.results.table(iterated_results_table,
response_variable_selected,
metaecosystem_type_selected,
model_stats_full,
model_stats_reduced)
iterated_results_table$set[nrow(iterated_results_table)] = set_i
iterated_results_table$system_nr_unconnected_systems[nrow(iterated_results_table)] =
paste(system_nr_unconnected_systems_selected, collapse = " ")
}
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: Nelder_Mead "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: nlminbwrap "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: Nelder_Mead "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model fitting failed with all optimizers."
## This model could not be fitted with any optimiser. The unconnected meta-ecosystems in this iteration were: 1026 1034 1038 1042
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: nlminbwrap "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
Full vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
data.frame(deltaAIC = median(iterated_results_table$ΔAIC_full),
p_value = median(iterated_results_table$p_full),
R2 = NA) %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -2 0.051 * weak
# --- FULL VS NULL MODEL - SHOW ΔAIC & P VALUE DISTRIBUTIONS --- #
hist(iterated_results_table$ΔAIC_full, main = "Distribution of ΔAIC of the full model.")
hist(iterated_results_table$p_full, main = "Distribution of p-values of the full model.")
# --- FULL VS NULL MODEL - SHOW WHICH UNCONNECTED META-ECOSYSTEM NUMBER PRODUCD WHICH AIC --- #
iterated_results_table %>%
select(system_nr_unconnected_systems,
ΔAIC_full) %>%
arrange(ΔAIC_full)
## system_nr_unconnected_systems ΔAIC_full
## 1 1028 1032 1040 1044 -5.12774064
## 2 1029 1032 1040 1043 -5.04693282
## 3 1026 1032 1040 1043 -4.87769475
## 4 1030 1032 1039 1043 -4.72558456
## 5 1028 1032 1040 1041 -4.53416911
## 6 1030 1032 1036 1043 -4.49211410
## 7 1028 1032 1039 1045 -4.28439971
## 8 1026 1032 1039 1043 -4.27936110
## 9 1029 1032 1036 1043 -4.25033880
## 10 1030 1033 1036 1044 -4.14837258
## 11 1028 1032 1036 1044 -4.08462596
## 12 1030 1032 1036 1044 -4.05163335
## 13 1030 1033 1039 1041 -4.03677099
## 14 1028 1032 1039 1041 -3.97766659
## 15 1030 1032 1039 1041 -3.86861078
## 16 1028 1032 1036 1045 -3.85560572
## 17 1029 1033 1040 1041 -3.67468746
## 18 1026 1032 1040 1044 -3.59296745
## 19 1029 1032 1040 1041 -3.57937324
## 20 1028 1031 1040 1044 -3.49383224
## 21 1030 1031 1039 1043 -3.26878982
## 22 1029 1033 1036 1045 -3.23087832
## 23 1029 1031 1040 1043 -3.19702121
## 24 1026 1033 1040 1044 -3.19321019
## 25 1027 1031 1040 1043 -3.16349404
## 26 1027 1034 1040 1043 -3.14887289
## 27 1029 1032 1036 1045 -3.03581025
## 28 1030 1034 1036 1043 -2.99569279
## 29 1030 1031 1037 1043 -2.98557628
## 30 1027 1033 1040 1044 -2.97852327
## 31 1030 1034 1037 1043 -2.94194125
## 32 1026 1034 1040 1043 -2.92280108
## 33 1027 1033 1040 1041 -2.84644219
## 34 1028 1034 1040 1041 -2.77123370
## 35 1026 1032 1039 1045 -2.71868842
## 36 1030 1032 1038 1044 -2.68853692
## 37 1028 1031 1040 1042 -2.66408214
## 38 1027 1033 1036 1044 -2.65362339
## 39 1028 1034 1040 1042 -2.61683485
## 40 1028 1031 1039 1045 -2.60310034
## 41 1027 1034 1036 1043 -2.54921559
## 42 1026 1033 1039 1045 -2.52176384
## 43 1026 1034 1037 1043 -2.51428769
## 44 1027 1031 1039 1043 -2.48039466
## 45 1027 1033 1039 1041 -2.46920720
## 46 1026 1035 1037 1043 -2.43209006
## 47 1027 1035 1036 1043 -2.42035832
## 48 1027 1033 1039 1045 -2.39387088
## 49 1030 1033 1039 1042 -2.33882931
## 50 1030 1033 1036 1042 -2.32396663
## 51 1030 1032 1038 1041 -2.31498714
## 52 1027 1033 1036 1045 -2.29476673
## 53 1028 1034 1036 1045 -2.22299588
## 54 1027 1035 1039 1043 -2.20908853
## 55 1029 1031 1037 1043 -2.15329171
## 56 1030 1033 1037 1044 -2.06491544
## 57 1026 1033 1040 1042 -2.02589563
## 58 1028 1035 1036 1044 -2.02010122
## 59 1029 1033 1040 1042 -2.01156836
## 60 1029 1035 1037 1043 -1.96163253
## 61 1028 1031 1039 1042 -1.95052302
## 62 1029 1035 1036 1043 -1.89207614
## 63 1026 1035 1039 1043 -1.83835935
## 64 1030 1033 1037 1041 -1.81350842
## 65 1026 1032 1038 1044 -1.77029957
## 66 1028 1031 1037 1044 -1.76575365
## 67 1029 1032 1038 1045 -1.73746484
## 68 1029 1033 1036 1042 -1.71822537
## 69 1028 1035 1039 1042 -1.64785233
## 70 1028 1034 1036 1042 -1.64640619
## 71 1029 1032 1038 1041 -1.60745596
## 72 1028 1035 1039 1041 -1.60138230
## 73 1026 1033 1039 1042 -1.52924528
## 74 1028 1035 1037 1044 -1.44396390
## 75 1028 1031 1037 1045 -1.40198141
## 76 1026 1032 1038 1045 -1.39767552
## 77 1028 1035 1036 1042 -1.39446354
## 78 1028 1034 1037 1045 -1.34222326
## 79 1028 1034 1037 1041 -1.24672907
## 80 1026 1033 1037 1044 -0.91983189
## 81 1028 1035 1037 1041 -0.91560314
## 82 1029 1033 1037 1041 -0.91424260
## 83 1029 1033 1037 1045 -0.84319332
## 84 1026 1033 1037 1045 -0.43208335
## 85 1030 1031 1038 1042 -0.40429638
## 86 1030 1034 1038 1042 -0.36111791
## 87 1030 1034 1036 1042 -0.19147329
## 88 1030 1031 1039 1042 -0.07218231
## 89 1026 1034 1040 1042 0.48176681
## 90 1026 1035 1038 1042 0.72602808
## 91 1029 1031 1038 1042 0.76526324
## 92 1029 1031 1040 1042 0.77888647
## 93 1029 1035 1038 1042 0.81490160
## 94 1030 1034 1038 1041 0.83348361
## 95 1030 1031 1038 1044 0.96677765
## 96 1026 1035 1039 1042 1.12405577
## 97 1029 1035 1036 1042 1.16762082
## 98 1030 1034 1037 1041 1.56257638
## 99 1030 1031 1037 1044 1.58913364
## 100 1027 1034 1040 1041 1.66787056
## 101 1027 1031 1040 1044 2.04790015
## 102 1027 1031 1039 1045 2.16190442
## 103 1029 1031 1038 1045 2.27845387
## 104 1027 1034 1036 1045 2.34717003
## 105 1027 1034 1038 1041 2.47160560
## 106 1027 1035 1038 1044 2.52458411
## 107 1027 1031 1038 1044 2.54112255
## 108 1027 1031 1038 1045 2.62928789
## 109 1029 1035 1038 1041 2.66574445
## 110 1027 1034 1038 1045 2.69468839
## 111 1026 1034 1038 1045 2.81800808
## 112 1026 1035 1038 1044 2.82669830
## 113 1027 1035 1036 1044 2.84240581
## 114 1027 1035 1038 1041 2.87736566
## 115 1029 1031 1037 1045 3.04563157
## 116 1027 1035 1039 1041 3.05539815
## 117 1026 1035 1037 1044 3.41451218
## 118 1029 1035 1037 1041 3.55949203
## 119 1026 1034 1037 1045 3.66750670
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
data.frame(deltaAIC = median(iterated_results_table$ΔAIC_fix),
p_value = median(iterated_results_table$p_fix),
R2 = NA) %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -3.5 0.019 ** moderate
# --- REDUCED VS NULL MODEL - SHOW ΔAIC & P VALUE --- #
hist(iterated_results_table$ΔAIC_fix, main = "Distribution of ΔAIC of the reduced model.")
hist(iterated_results_table$p_fix, main = "Distribution of p-values of the reduced model.")
# --- REDUCED VS NULL MODEL - SHOW WHICH UNCONNECTED META-ECOSYSTEM NUMBER PRODUCD WHICH AIC --- #
iterated_results_table %>%
select(system_nr_unconnected_systems,
ΔAIC_fix) %>%
arrange(ΔAIC_fix)
## system_nr_unconnected_systems ΔAIC_fix
## 1 1028 1032 1040 1044 -7.042816223
## 2 1029 1032 1040 1043 -6.925067504
## 3 1030 1032 1039 1043 -6.655814256
## 4 1028 1032 1040 1041 -6.489426561
## 5 1026 1032 1040 1043 -6.448130104
## 6 1030 1032 1036 1043 -6.282747760
## 7 1028 1032 1039 1045 -6.115343866
## 8 1028 1032 1036 1044 -6.038811744
## 9 1029 1032 1036 1043 -6.011441599
## 10 1026 1032 1039 1043 -5.937553124
## 11 1030 1032 1036 1044 -5.932932908
## 12 1028 1032 1039 1041 -5.888522351
## 13 1028 1032 1036 1045 -5.790089304
## 14 1026 1032 1040 1044 -5.570342161
## 15 1030 1032 1039 1041 -5.521718364
## 16 1030 1031 1039 1043 -5.244577771
## 17 1029 1032 1040 1041 -5.182442357
## 18 1029 1031 1040 1043 -5.116984635
## 19 1030 1034 1036 1043 -4.967974889
## 20 1029 1032 1036 1045 -4.830749462
## 21 1030 1032 1038 1044 -4.679705229
## 22 1030 1033 1036 1044 -4.674812783
## 23 1028 1031 1040 1042 -4.653466382
## 24 1027 1034 1040 1043 -4.625670250
## 25 1028 1034 1040 1042 -4.613371190
## 26 1028 1031 1040 1044 -4.606859082
## 27 1027 1031 1040 1043 -4.599744827
## 28 1026 1032 1039 1045 -4.597237640
## 29 1030 1031 1037 1043 -4.583095855
## 30 1030 1034 1037 1043 -4.572702822
## 31 1026 1034 1040 1043 -4.534630620
## 32 1030 1033 1039 1042 -4.338661594
## 33 1026 1033 1040 1044 -4.319594671
## 34 1030 1033 1036 1042 -4.318288365
## 35 1030 1032 1038 1041 -4.304828966
## 36 1030 1033 1039 1041 -4.238530791
## 37 1027 1033 1040 1044 -4.168294286
## 38 1027 1033 1036 1044 -4.038481496
## 39 1029 1033 1040 1042 -4.011163235
## 40 1027 1031 1039 1043 -3.974254574
## 41 1028 1031 1039 1042 -3.948251623
## 42 1026 1033 1040 1042 -3.894425991
## 43 1027 1034 1036 1043 -3.787209227
## 44 1026 1032 1038 1044 -3.737587342
## 45 1027 1033 1040 1041 -3.725933242
## 46 1028 1034 1040 1041 -3.705259569
## 47 1029 1033 1036 1042 -3.703406756
## 48 1029 1032 1038 1045 -3.700522535
## 49 1028 1031 1037 1044 -3.688156632
## 50 1029 1035 1036 1043 -3.676190764
## 51 1029 1031 1037 1043 -3.640839186
## 52 1028 1034 1036 1042 -3.640051266
## 53 1028 1035 1039 1042 -3.625162772
## 54 1029 1032 1038 1041 -3.565969748
## 55 1028 1031 1039 1045 -3.554427224
## 56 1029 1033 1040 1041 -3.551968058
## 57 1027 1033 1036 1045 -3.490560306
## 58 1026 1033 1039 1042 -3.475556108
## 59 1030 1033 1037 1044 -3.465267836
## 60 1027 1033 1039 1045 -3.462409388
## 61 1028 1035 1037 1044 -3.433539180
## 62 1027 1033 1039 1041 -3.428940866
## 63 1026 1032 1038 1045 -3.390239934
## 64 1029 1033 1036 1045 -3.341623220
## 65 1028 1035 1036 1042 -3.335133792
## 66 1027 1035 1039 1043 -3.333993234
## 67 1026 1033 1039 1045 -3.314686741
## 68 1028 1031 1037 1045 -3.304921644
## 69 1028 1035 1036 1044 -3.292267088
## 70 1026 1035 1039 1043 -3.273997098
## 71 1026 1034 1037 1043 -3.273893982
## 72 1028 1034 1037 1045 -3.227056865
## 73 1030 1033 1037 1041 -3.186035672
## 74 1028 1034 1037 1041 -3.153100484
## 75 1029 1035 1037 1043 -3.149311190
## 76 1028 1034 1036 1045 -3.061558661
## 77 1027 1035 1036 1043 -3.018659842
## 78 1028 1035 1037 1041 -2.907766072
## 79 1026 1033 1037 1044 -2.812608774
## 80 1028 1035 1039 1041 -2.808873673
## 81 1026 1035 1037 1043 -2.538851246
## 82 1026 1033 1037 1045 -2.261733970
## 83 1029 1033 1037 1045 -2.198479372
## 84 1029 1033 1037 1041 -2.195049506
## 85 1030 1031 1038 1042 -2.093580633
## 86 1030 1034 1038 1042 -2.059134597
## 87 1030 1034 1036 1042 -1.965722216
## 88 1030 1031 1039 1042 -1.941587568
## 89 1029 1031 1040 1042 -0.965681471
## 90 1029 1031 1038 1042 -0.781730950
## 91 1030 1031 1038 1044 -0.649600662
## 92 1026 1034 1040 1042 -0.569354166
## 93 1029 1035 1038 1042 -0.543038860
## 94 1030 1034 1038 1041 -0.349749547
## 95 1029 1035 1036 1042 -0.192474261
## 96 1030 1031 1037 1044 -0.003118547
## 97 1026 1035 1038 1042 0.180810159
## 98 1030 1034 1037 1041 0.228245331
## 99 1026 1035 1039 1042 0.356404900
## 100 1027 1031 1038 1044 0.559406460
## 101 1027 1035 1038 1044 0.580946732
## 102 1027 1031 1040 1044 0.651327329
## 103 1027 1034 1038 1041 0.652120235
## 104 1027 1031 1038 1045 0.706488012
## 105 1027 1034 1038 1045 0.758846897
## 106 1029 1031 1038 1045 0.819948749
## 107 1026 1035 1038 1044 0.827262033
## 108 1027 1035 1036 1044 0.862339925
## 109 1027 1035 1038 1041 0.877376263
## 110 1026 1034 1038 1045 0.942033099
## 111 1027 1034 1036 1045 1.084200795
## 112 1029 1035 1038 1041 1.084986169
## 113 1027 1034 1040 1041 1.087693007
## 114 1027 1031 1039 1045 1.148581286
## 115 1026 1035 1037 1044 1.540826175
## 116 1027 1035 1039 1041 1.604048823
## 117 1029 1031 1037 1045 1.656554610
## 118 1026 1034 1037 1045 1.718602952
## 119 1029 1035 1037 1041 1.768430164
metaecosystem_type_selected = c("Medium-Medium")
Our first step in the data analysis involves filtering the data to isolate the relevant data. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure we filtered data the right way.
# --- FILTER DATA --- #
filtered_data = ds_metaecosystems %>%
filter(time_point %in% time_points_model,
metaecosystem_type %in% metaecosystem_type_selected,
!is.na(!!sym("total_water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.metaecos.points(filtered_data,
metaecosystem_type_selected,
connection_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same meta-ecosystem on multiple occasions, we can develop mixed effect models to examine how the connection influenced this meta-ecosystem variable. To study the effects of connection we compare two models to a null model using ANOVA: a full model and a reduced model. In all models, we treat system nr as having a random effect on how the slope and intercept of the relationship between response variable and time, with the slope and intercept being correlated (Bates et al. 2015). We also include the total water that was added due to evaporation in the microwave and the time point before the first disturbance (baseline). In the syntax of lmer4 the three models look this this:
Full model = response_variable ~connection * scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Reduced model = response_variable ~connection + scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Null model = response_variable ~scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Unconnected meta-ecosystems are made of paired unconnected
ecosystems, which are paired randomly. However, how to pair unconnected
ecosystems can be done in multiple ways, as unconnected ecosystems did
not interact and therefore any combination between ecosystems would be
arbitrary. To make sure that the random combination we selected did not
bias our results, we run all the possible combinations of ecosystems
constituting unconnected meta-ecosystems. The ecosystem combinations are
into the objects unconnected_combinations_sets (Data >
Meta-ecosystems). We therefore compute a p-value for each unconnected
ecosystems combination, creating a p-value distribution. We keep as
p-value of the comparison the median of such distributions.
# --- ADD BASELINES --- #
baselines = ds_metaecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(system_nr,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- PREPARE TO COMPARE FULL, REDUCED, AND NULL MODEL WHILE RESHUFFLING ECOSYSTEM COMBINATIONS --- #
unconnected_combinations_sets_filtered = unconnected_combinations_sets %>%
filter(disturbance == disturbance_global_selected,
metaecosystem_type %in% metaecosystem_type_selected)
n_sets = unconnected_combinations_sets_filtered %>%
pull(set) %>%
max()
iterated_results_table = data.frame(Response = as.character(NA),
Levels = as.character(NA),
ΔAIC_full = NA,
p_full = NA,
ΔR2_full = NA,
ΔAIC_fix = NA,
p_fix = NA,
ΔR2_fix = NA,
combination_set = NA,
system_nr_unconnected_systems = as.character(NA)) %>%
slice(-1)
# --- COMPARE FULL, REDUCED, AND NULL MODEL WHILE RESHUFFLING ECOSYSTEM COMBINATIONS --- #
for (set_i in 1:n_sets) {
# Filter the data to contain all the connected meta-ecosystems and only a subset of unconnected meta-ecosystems
system_nr_unconnected_systems_selected = unconnected_combinations_sets_filtered %>%
filter(metaecosystem_type %in% metaecosystem_type_selected,
connection == "unconnected",
set == set_i) %>%
pull(system_nr)
filtered_data_2 = filtered_data %>%
filter(connection == "connected" |
(connection == "unconnected" &
system_nr %in% system_nr_unconnected_systems_selected))
# Construct models
full_model = try.different.optimizer.full.model()
reduced_model = try.different.optimizer.reduced.model()
null_model = try.different.optimizer.null.model()
# If all the optimisers fail, move on to the next iteration
if (is.null(full_model) || is.null(reduced_model) || is.null(null_model)) {
cat("This model could not be fitted with any optimiser. The unconnected meta-ecosystems in this iteration were:",
system_nr_unconnected_systems_selected,
"\n")
next
}
if(plot_model_residuals_metaecos == TRUE){
# Plot residuals - full model
print(qqnorm(resid(full_model))); print(qqline(resid(full_model)))
#full_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, full_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(full_model),
residuals = resid(full_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_full_model.png")),
plot = plot,
width = 8,
height = 6)
# Plot residuals - reduced model
print(qqnorm(resid(reduced_model))); print(qqline(resid(reduced_model)))
#reduced_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, reduced_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(reduced_model),
residuals = resid(reduced_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_reduced_model.png")),
plot = plot,
width = 8,
height = 6)
# Plot residuals - null model
print(qqnorm(resid(null_model))); print(qqline(resid(null_model)))
#null_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, null_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(null_model),
residuals = resid(null_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_null_model.png")),
plot = plot,
width = 8,
height = 6)
}
# Give model statistics
model_stats_full = compute.model.stats(full_model,
null_model,
"mixed_model")
model_stats_reduced = compute.model.stats(reduced_model,
null_model,
"mixed_model")
# Save model statistics
iterated_results_table = fill.results.table(iterated_results_table,
response_variable_selected,
metaecosystem_type_selected,
model_stats_full,
model_stats_reduced)
iterated_results_table$set[nrow(iterated_results_table)] = set_i
iterated_results_table$system_nr_unconnected_systems[nrow(iterated_results_table)] =
paste(system_nr_unconnected_systems_selected, collapse = " ")
}
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: optimx (L-BFGS-B)"
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: optimx (L-BFGS-B)"
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
Full vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
data.frame(deltaAIC = median(iterated_results_table$ΔAIC_full),
p_value = median(iterated_results_table$p_full),
R2 = NA) %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 3 0.617 none
# --- FULL VS NULL MODEL - SHOW ΔAIC & P VALUE DISTRIBUTIONS --- #
hist(iterated_results_table$ΔAIC_full, main = "Distribution of ΔAIC of the full model.")
hist(iterated_results_table$p_full, main = "Distribution of p-values of the full model.")
# --- FULL VS NULL MODEL - SHOW WHICH UNCONNECTED META-ECOSYSTEM NUMBER PRODUCD WHICH AIC --- #
iterated_results_table %>%
select(system_nr_unconnected_systems,
ΔAIC_full) %>%
arrange(ΔAIC_full)
## system_nr_unconnected_systems ΔAIC_full
## 1 1059 1060 -0.8030221
## 2 1060 1059 -0.8030221
## 3 1058 1062 0.8135608
## 4 1062 1058 0.8135608
## 5 1059 1061 0.9522385
## 6 1061 1059 0.9522385
## 7 1061 1064 1.4994572
## 8 1064 1061 1.4994572
## 9 1060 1065 1.6487373
## 10 1065 1060 1.6487373
## 11 1056 1063 2.6278095
## 12 1063 1056 2.6278095
## 13 1057 1062 2.7298325
## 14 1062 1057 2.7298325
## 15 1062 1063 3.0340578
## 16 1063 1062 3.0340578
## 17 1059 1063 3.1532035
## 18 1063 1059 3.1532035
## 19 1058 1060 3.5973365
## 20 1060 1058 3.5973365
## 21 1056 1064 3.6432429
## 22 1064 1056 3.6432429
## 23 1057 1061 3.6470696
## 24 1061 1057 3.6470696
## 25 1058 1064 3.6909473
## 26 1064 1058 3.6909473
## 27 1057 1065 3.7769136
## 28 1065 1057 3.7769136
## 29 1056 1065 3.8615663
## 30 1065 1056 3.8615663
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
data.frame(deltaAIC = median(iterated_results_table$ΔAIC_fix),
p_value = median(iterated_results_table$p_fix),
R2 = NA) %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 1.6 0.53 none
# --- REDUCED VS NULL MODEL - SHOW ΔAIC & P VALUE --- #
hist(iterated_results_table$ΔAIC_fix, main = "Distribution of ΔAIC of the reduced model.")
hist(iterated_results_table$p_fix, main = "Distribution of p-values of the reduced model.")
# --- REDUCED VS NULL MODEL - SHOW WHICH UNCONNECTED META-ECOSYSTEM NUMBER PRODUCD WHICH AIC --- #
iterated_results_table %>%
select(system_nr_unconnected_systems,
ΔAIC_fix) %>%
arrange(ΔAIC_fix)
## system_nr_unconnected_systems ΔAIC_fix
## 1 1059 1061 -0.2901792
## 2 1061 1059 -0.2901792
## 3 1058 1062 0.1325808
## 4 1062 1058 0.1325808
## 5 1059 1060 0.8682064
## 6 1060 1059 0.8682064
## 7 1057 1062 0.9190793
## 8 1062 1057 0.9190793
## 9 1061 1064 1.0906994
## 10 1064 1061 1.0906994
## 11 1062 1063 1.1133365
## 12 1063 1062 1.1133365
## 13 1059 1063 1.4726420
## 14 1063 1059 1.4726420
## 15 1058 1060 1.6055638
## 16 1060 1058 1.6055638
## 17 1056 1064 1.6496808
## 18 1064 1056 1.6496808
## 19 1057 1061 1.7090154
## 20 1061 1057 1.7090154
## 21 1058 1064 1.7352787
## 22 1064 1058 1.7352787
## 23 1057 1065 1.8602143
## 24 1065 1057 1.8602143
## 25 1056 1063 1.9137390
## 26 1063 1056 1.9137390
## 27 1056 1065 1.9204500
## 28 1065 1056 1.9204500
## 29 1060 1065 1.9898465
## 30 1065 1060 1.9898465
Following the initial inspection, we proceed to analyse differences among meta-ecosystems. To make it easier to interpret differences, we decided to construct a model for each comparisons we are interested in, which are: SL (connected vs unconnected) and MM (connected vs unconnected).
response_variable_selected = "metaecosystem_richness"
metaecosystem_type_selected = c("Medium-Medium",
"Small-Large")
Here we want to look at how this meta-ecosystem variable changed across time by plotting its mean ± 95 confidence interval:
plot.metaecos.points(ds_metaecosystems,
metaecosystem_type_selected,
connection_selected,
response_variable_selected)
plot.metaecos.replicates(ds_metaecosystems,
metaecosystem_type_selected,
response_variable_selected)
metaecosystem_type_selected = c("Small-Large")
Our first step in the data analysis involves filtering the data to isolate the relevant data. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure we filtered data the right way.
# --- FILTER DATA --- #
filtered_data = ds_metaecosystems %>%
filter(time_point %in% time_points_model,
metaecosystem_type %in% metaecosystem_type_selected,
!is.na(!!sym("total_water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.metaecos.points(filtered_data,
metaecosystem_type_selected,
connection_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same meta-ecosystem on multiple occasions, we can develop mixed effect models to examine how the connection influenced this meta-ecosystem variable. To study the effects of connection we compare two models to a null model using ANOVA: a full model and a reduced model. In all models, we treat system nr as having a random effect on how the slope and intercept of the relationship between response variable and time, with the slope and intercept being correlated (Bates et al. 2015). We also include the total water that was added due to evaporation in the microwave and the time point before the first disturbance (baseline). In the syntax of lmer4 the three models look this this:
Full model = response_variable ~connection * scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Reduced model = response_variable ~connection + scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Null model = response_variable ~scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Unconnected meta-ecosystems are made of paired unconnected
ecosystems, which are paired randomly. However, how to pair unconnected
ecosystems can be done in multiple ways, as unconnected ecosystems did
not interact and therefore any combination between ecosystems would be
arbitrary. To make sure that the random combination we selected did not
bias our results, we run all the possible combinations of ecosystems
constituting unconnected meta-ecosystems. The ecosystem combinations are
into the objects unconnected_combinations_sets (Data >
Meta-ecosystems). We therefore compute a p-value for each unconnected
ecosystems combination, creating a p-value distribution. We keep as
p-value of the comparison the median of such distributions.
# --- ADD BASELINES --- #
baselines = ds_metaecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(system_nr,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- PREPARE TO COMPARE FULL, REDUCED, AND NULL MODEL WHILE RESHUFFLING ECOSYSTEM COMBINATIONS --- #
unconnected_combinations_sets_filtered = unconnected_combinations_sets %>%
filter(disturbance == disturbance_global_selected,
metaecosystem_type %in% metaecosystem_type_selected)
n_sets = unconnected_combinations_sets_filtered %>%
pull(set) %>%
max()
iterated_results_table = data.frame(Response = as.character(NA),
Levels = as.character(NA),
ΔAIC_full = NA,
p_full = NA,
ΔR2_full = NA,
ΔAIC_fix = NA,
p_fix = NA,
ΔR2_fix = NA,
combination_set = NA,
system_nr_unconnected_systems = as.character(NA)) %>%
slice(-1)
# --- COMPARE FULL, REDUCED, AND NULL MODEL WHILE RESHUFFLING ECOSYSTEM COMBINATIONS --- #
for (set_i in 1:n_sets) {
# Filter the data to contain all the connected meta-ecosystems and only a subset of unconnected meta-ecosystems
system_nr_unconnected_systems_selected = unconnected_combinations_sets_filtered %>%
filter(metaecosystem_type %in% metaecosystem_type_selected,
connection == "unconnected",
set == set_i) %>%
pull(system_nr)
filtered_data_2 = filtered_data %>%
filter(connection == "connected" |
(connection == "unconnected" &
system_nr %in% system_nr_unconnected_systems_selected))
# Construct models
full_model = try.different.optimizer.full.model()
reduced_model = try.different.optimizer.reduced.model()
null_model = try.different.optimizer.null.model()
# If all the optimisers fail, move on to the next iteration
if (is.null(full_model) || is.null(reduced_model) || is.null(null_model)) {
cat("This model could not be fitted with any optimiser. The unconnected meta-ecosystems in this iteration were:",
system_nr_unconnected_systems_selected,
"\n")
next
}
if(plot_model_residuals_metaecos == TRUE){
# Plot residuals - full model
print(qqnorm(resid(full_model))); print(qqline(resid(full_model)))
#full_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, full_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(full_model),
residuals = resid(full_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_full_model.png")),
plot = plot,
width = 8,
height = 6)
# Plot residuals - reduced model
print(qqnorm(resid(reduced_model))); print(qqline(resid(reduced_model)))
#reduced_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, reduced_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(reduced_model),
residuals = resid(reduced_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_reduced_model.png")),
plot = plot,
width = 8,
height = 6)
# Plot residuals - null model
print(qqnorm(resid(null_model))); print(qqline(resid(null_model)))
#null_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, null_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(null_model),
residuals = resid(null_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_null_model.png")),
plot = plot,
width = 8,
height = 6)
}
# Give model statistics
model_stats_full = compute.model.stats(full_model,
null_model,
"mixed_model")
model_stats_reduced = compute.model.stats(reduced_model,
null_model,
"mixed_model")
# Save model statistics
iterated_results_table = fill.results.table(iterated_results_table,
response_variable_selected,
metaecosystem_type_selected,
model_stats_full,
model_stats_reduced)
iterated_results_table$set[nrow(iterated_results_table)] = set_i
iterated_results_table$system_nr_unconnected_systems[nrow(iterated_results_table)] =
paste(system_nr_unconnected_systems_selected, collapse = " ")
}
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
Full vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
data.frame(deltaAIC = median(iterated_results_table$ΔAIC_full),
p_value = median(iterated_results_table$p_full),
R2 = NA) %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 1.7 0.319 none
# --- FULL VS NULL MODEL - SHOW ΔAIC & P VALUE DISTRIBUTIONS --- #
hist(iterated_results_table$ΔAIC_full, main = "Distribution of ΔAIC of the full model.")
hist(iterated_results_table$p_full, main = "Distribution of p-values of the full model.")
# --- FULL VS NULL MODEL - SHOW WHICH UNCONNECTED META-ECOSYSTEM NUMBER PRODUCD WHICH AIC --- #
iterated_results_table %>%
select(system_nr_unconnected_systems,
ΔAIC_full) %>%
arrange(ΔAIC_full)
## system_nr_unconnected_systems ΔAIC_full
## 1 1030 1033 1036 1044 -2.04587474
## 2 1026 1033 1040 1044 -1.49605537
## 3 1030 1033 1039 1041 -1.20543999
## 4 1028 1031 1040 1044 -0.86158244
## 5 1026 1035 1038 1044 -0.81428736
## 6 1030 1031 1038 1044 -0.76297457
## 7 1026 1033 1039 1045 -0.76278037
## 8 1030 1033 1036 1042 -0.68476999
## 9 1029 1033 1036 1045 -0.60502764
## 10 1028 1035 1037 1041 -0.54973900
## 11 1026 1033 1040 1042 -0.31358991
## 12 1028 1035 1039 1041 -0.25509639
## 13 1030 1033 1037 1041 -0.09674302
## 14 1028 1031 1040 1042 -0.09255543
## 15 1029 1033 1040 1041 -0.03916071
## 16 1028 1035 1036 1044 0.06758408
## 17 1026 1035 1038 1042 0.12141284
## 18 1029 1031 1038 1045 0.14778028
## 19 1030 1031 1038 1042 0.16409048
## 20 1029 1035 1038 1041 0.18934250
## 21 1026 1032 1038 1045 0.22091625
## 22 1027 1031 1038 1045 0.24759566
## 23 1026 1032 1038 1044 0.25150093
## 24 1027 1031 1038 1044 0.30142561
## 25 1028 1032 1040 1041 0.32473332
## 26 1026 1033 1037 1045 0.32901119
## 27 1027 1033 1036 1045 0.37381326
## 28 1028 1031 1037 1045 0.42789410
## 29 1028 1031 1037 1044 0.50562261
## 30 1027 1035 1038 1041 0.65180773
## 31 1030 1034 1038 1041 0.68377217
## 32 1030 1032 1038 1041 0.68890625
## 33 1028 1031 1039 1045 0.77893571
## 34 1027 1033 1036 1044 0.83913402
## 35 1028 1032 1036 1044 0.87601901
## 36 1026 1033 1037 1044 0.87789531
## 37 1028 1035 1036 1042 0.90272892
## 38 1027 1033 1040 1041 0.91029396
## 39 1030 1033 1037 1044 0.95124818
## 40 1026 1034 1038 1045 1.02069873
## 41 1028 1034 1040 1041 1.03261598
## 42 1029 1031 1038 1042 1.09871920
## 43 1026 1035 1037 1043 1.11575510
## 44 1028 1032 1036 1045 1.11595203
## 45 1030 1031 1037 1043 1.17414532
## 46 1026 1035 1039 1043 1.19076309
## 47 1026 1032 1040 1043 1.24151205
## 48 1029 1033 1036 1042 1.27916765
## 49 1027 1033 1040 1044 1.29724984
## 50 1027 1031 1040 1043 1.32540911
## 51 1028 1032 1040 1044 1.36834177
## 52 1030 1033 1039 1042 1.41242714
## 53 1030 1031 1039 1043 1.45512600
## 54 1029 1033 1040 1042 1.59058824
## 55 1030 1032 1036 1043 1.62202025
## 56 1028 1031 1039 1042 1.63308176
## 57 1027 1035 1036 1043 1.63674001
## 58 1029 1031 1040 1043 1.64600650
## 59 1026 1033 1039 1042 1.65373166
## 60 1026 1034 1038 1042 1.70850685
## 61 1028 1035 1037 1044 1.71579261
## 62 1029 1035 1036 1043 1.80056456
## 63 1027 1035 1038 1044 1.82966022
## 64 1028 1032 1039 1041 1.83572350
## 65 1029 1032 1038 1041 1.87700697
## 66 1030 1032 1038 1044 1.89380826
## 67 1026 1032 1040 1044 1.91640199
## 68 1028 1034 1036 1045 1.96287681
## 69 1027 1031 1040 1044 1.97896176
## 70 1029 1031 1037 1043 2.04998012
## 71 1026 1034 1040 1043 2.08716275
## 72 1026 1032 1039 1043 2.10912668
## 73 1029 1032 1036 1043 2.12374093
## 74 1027 1031 1039 1043 2.19625832
## 75 1029 1033 1037 1041 2.23504862
## 76 1026 1035 1037 1044 2.24477327
## 77 1030 1031 1037 1044 2.27597432
## 78 1030 1034 1036 1043 2.31406490
## 79 1028 1034 1037 1041 2.31488537
## 80 1029 1032 1038 1045 2.31806721
## 81 1028 1034 1036 1042 2.35035967
## 82 1029 1032 1040 1043 2.35749067
## 83 1027 1033 1039 1045 2.36515342
## 84 1029 1035 1038 1042 2.38589201
## 85 1027 1034 1038 1041 2.38905160
## 86 1029 1033 1037 1045 2.44462808
## 87 1027 1033 1039 1041 2.46161296
## 88 1028 1035 1039 1042 2.49578574
## 89 1030 1032 1036 1044 2.51692205
## 90 1027 1035 1036 1044 2.52085320
## 91 1026 1034 1037 1043 2.57491126
## 92 1028 1032 1039 1045 2.64269640
## 93 1028 1034 1040 1042 2.67965960
## 94 1027 1034 1036 1043 2.69812077
## 95 1029 1031 1040 1042 2.71245910
## 96 1030 1032 1039 1043 2.74317040
## 97 1027 1035 1039 1043 2.77417729
## 98 1030 1034 1038 1042 2.81037837
## 99 1026 1032 1039 1045 2.81853452
## 100 1027 1034 1038 1045 2.82025097
## 101 1029 1035 1037 1043 2.82947991
## 102 1029 1032 1036 1045 2.87047520
## 103 1027 1031 1039 1045 2.88558969
## 104 1027 1034 1040 1043 2.89409046
## 105 1026 1035 1039 1042 2.89757472
## 106 1030 1031 1039 1042 2.94702307
## 107 1029 1032 1040 1041 2.99092371
## 108 1029 1031 1037 1045 3.03429669
## 109 1026 1034 1040 1042 3.09555359
## 110 1029 1035 1036 1042 3.17868525
## 111 1029 1035 1037 1041 3.26096830
## 112 1030 1032 1039 1041 3.27355613
## 113 1030 1034 1037 1043 3.29424278
## 114 1027 1035 1039 1041 3.33986224
## 115 1027 1034 1036 1045 3.35235649
## 116 1027 1034 1040 1041 3.39687435
## 117 1028 1034 1037 1045 3.40624095
## 118 1026 1034 1037 1045 3.42455331
## 119 1030 1034 1037 1041 3.50680359
## 120 1030 1034 1036 1042 3.52254838
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
data.frame(deltaAIC = median(iterated_results_table$ΔAIC_fix),
p_value = median(iterated_results_table$p_fix),
R2 = NA) %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 0 0.162 none
# --- REDUCED VS NULL MODEL - SHOW ΔAIC & P VALUE --- #
hist(iterated_results_table$ΔAIC_fix, main = "Distribution of ΔAIC of the reduced model.")
hist(iterated_results_table$p_fix, main = "Distribution of p-values of the reduced model.")
# --- REDUCED VS NULL MODEL - SHOW WHICH UNCONNECTED META-ECOSYSTEM NUMBER PRODUCD WHICH AIC --- #
iterated_results_table %>%
select(system_nr_unconnected_systems,
ΔAIC_fix) %>%
arrange(ΔAIC_fix)
## system_nr_unconnected_systems ΔAIC_fix
## 1 1026 1033 1040 1044 -2.011726845
## 2 1028 1031 1040 1044 -1.657294800
## 3 1026 1032 1038 1044 -1.617064440
## 4 1030 1033 1036 1044 -1.602018028
## 5 1026 1033 1040 1042 -1.591651803
## 6 1027 1031 1038 1044 -1.568965687
## 7 1028 1031 1040 1042 -1.519292705
## 8 1028 1031 1037 1044 -1.394575828
## 9 1030 1033 1036 1042 -1.335824791
## 10 1026 1032 1038 1045 -1.296470644
## 11 1027 1031 1038 1045 -1.278189399
## 12 1027 1033 1036 1045 -1.193429442
## 13 1026 1033 1037 1045 -1.174016018
## 14 1026 1033 1037 1044 -1.118043466
## 15 1028 1032 1040 1041 -1.115411226
## 16 1028 1035 1037 1041 -1.110273788
## 17 1028 1032 1036 1044 -1.109745886
## 18 1027 1033 1036 1044 -1.087101940
## 19 1026 1035 1038 1044 -1.047898515
## 20 1030 1033 1037 1041 -1.044604229
## 21 1030 1031 1038 1044 -1.042349147
## 22 1028 1031 1037 1045 -0.954809877
## 23 1026 1035 1038 1042 -0.951935381
## 24 1030 1031 1038 1042 -0.917716400
## 25 1026 1033 1039 1045 -0.803769320
## 26 1027 1033 1040 1041 -0.802297189
## 27 1026 1035 1037 1043 -0.761668167
## 28 1026 1032 1040 1043 -0.756936419
## 29 1028 1032 1036 1045 -0.726650684
## 30 1030 1031 1037 1043 -0.726315681
## 31 1030 1033 1037 1044 -0.700690731
## 32 1028 1035 1036 1044 -0.683483398
## 33 1027 1033 1040 1044 -0.673332236
## 34 1027 1031 1040 1043 -0.672573059
## 35 1029 1031 1038 1042 -0.657376095
## 36 1029 1033 1036 1045 -0.655182855
## 37 1028 1032 1040 1044 -0.625070852
## 38 1028 1035 1036 1042 -0.553759303
## 39 1029 1033 1040 1041 -0.504444792
## 40 1029 1033 1036 1042 -0.456780859
## 41 1027 1035 1038 1041 -0.437338096
## 42 1030 1032 1038 1041 -0.409673228
## 43 1030 1032 1036 1043 -0.365757537
## 44 1027 1035 1036 1043 -0.347375402
## 45 1030 1033 1039 1041 -0.305455659
## 46 1029 1031 1038 1045 -0.292022689
## 47 1026 1033 1039 1042 -0.260195085
## 48 1028 1031 1039 1042 -0.259342248
## 49 1029 1033 1040 1042 -0.208676936
## 50 1029 1031 1040 1043 -0.175003936
## 51 1028 1035 1037 1044 -0.116949512
## 52 1026 1035 1039 1043 -0.114466541
## 53 1027 1035 1038 1044 -0.091171429
## 54 1028 1032 1039 1041 -0.087898498
## 55 1030 1032 1038 1044 -0.037271639
## 56 1029 1032 1038 1041 -0.034563087
## 57 1030 1033 1039 1042 -0.027226291
## 58 1026 1032 1040 1044 -0.012523985
## 59 1030 1031 1039 1043 0.007746461
## 60 1026 1034 1038 1042 0.035383473
## 61 1027 1031 1040 1044 0.055245887
## 62 1029 1035 1036 1043 0.230752544
## 63 1028 1031 1039 1045 0.238498677
## 64 1026 1035 1037 1044 0.249415314
## 65 1029 1033 1037 1041 0.276823640
## 66 1030 1031 1037 1044 0.277991354
## 67 1029 1032 1036 1043 0.312028854
## 68 1028 1035 1039 1041 0.313872215
## 69 1026 1034 1040 1043 0.356287793
## 70 1029 1032 1038 1045 0.356376939
## 71 1027 1033 1039 1045 0.371025611
## 72 1028 1034 1037 1041 0.466454617
## 73 1029 1035 1038 1041 0.468527682
## 74 1029 1033 1037 1045 0.469351206
## 75 1028 1034 1036 1042 0.474134481
## 76 1027 1033 1039 1041 0.480446328
## 77 1029 1031 1037 1043 0.490028544
## 78 1026 1032 1039 1043 0.523114066
## 79 1027 1035 1036 1044 0.545074882
## 80 1030 1032 1036 1044 0.545245730
## 81 1027 1034 1038 1041 0.559518788
## 82 1028 1035 1039 1042 0.579002964
## 83 1029 1035 1038 1042 0.590333589
## 84 1027 1031 1039 1043 0.619622294
## 85 1028 1032 1039 1045 0.646239802
## 86 1029 1032 1040 1043 0.657294475
## 87 1029 1031 1040 1042 0.737431075
## 88 1028 1034 1040 1042 0.793355980
## 89 1027 1034 1036 1043 0.795878997
## 90 1026 1034 1038 1045 0.802350725
## 91 1028 1034 1040 1041 0.824516842
## 92 1030 1034 1036 1043 0.843311631
## 93 1026 1034 1037 1043 0.853812846
## 94 1029 1035 1037 1043 0.901616868
## 95 1030 1032 1039 1043 0.903407329
## 96 1026 1035 1039 1042 0.908598307
## 97 1027 1034 1038 1045 0.925510990
## 98 1027 1035 1039 1043 0.928078703
## 99 1030 1031 1039 1042 0.951731605
## 100 1029 1032 1036 1045 0.979093256
## 101 1026 1032 1039 1045 0.983057935
## 102 1027 1031 1039 1045 1.063206145
## 103 1027 1034 1040 1043 1.076901938
## 104 1026 1034 1040 1042 1.099398447
## 105 1030 1034 1038 1042 1.116760373
## 106 1029 1031 1037 1045 1.137688750
## 107 1029 1032 1040 1041 1.162690007
## 108 1029 1035 1036 1042 1.179440014
## 109 1030 1034 1038 1041 1.242048479
## 110 1028 1034 1036 1045 1.252949816
## 111 1029 1035 1037 1041 1.262077358
## 112 1030 1032 1039 1041 1.275865910
## 113 1030 1034 1037 1043 1.322945550
## 114 1027 1035 1039 1041 1.342999001
## 115 1027 1034 1036 1045 1.388984397
## 116 1026 1034 1037 1045 1.452846596
## 117 1027 1034 1040 1041 1.479423588
## 118 1028 1034 1037 1045 1.507662233
## 119 1030 1034 1037 1041 1.513330012
## 120 1030 1034 1036 1042 1.528724221
metaecosystem_type_selected = c("Medium-Medium")
Our first step in the data analysis involves filtering the data to isolate the relevant data. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure we filtered data the right way.
# --- FILTER DATA --- #
filtered_data = ds_metaecosystems %>%
filter(time_point %in% time_points_model,
metaecosystem_type %in% metaecosystem_type_selected,
!is.na(!!sym("total_water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.metaecos.points(filtered_data,
metaecosystem_type_selected,
connection_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same meta-ecosystem on multiple occasions, we can develop mixed effect models to examine how the connection influenced this meta-ecosystem variable. To study the effects of connection we compare two models to a null model using ANOVA: a full model and a reduced model. In all models, we treat system nr as having a random effect on how the slope and intercept of the relationship between response variable and time, with the slope and intercept being correlated (Bates et al. 2015). We also include the total water that was added due to evaporation in the microwave and the time point before the first disturbance (baseline). In the syntax of lmer4 the three models look this this:
Full model = response_variable ~connection * scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Reduced model = response_variable ~connection + scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Null model = response_variable ~scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Unconnected meta-ecosystems are made of paired unconnected
ecosystems, which are paired randomly. However, how to pair unconnected
ecosystems can be done in multiple ways, as unconnected ecosystems did
not interact and therefore any combination between ecosystems would be
arbitrary. To make sure that the random combination we selected did not
bias our results, we run all the possible combinations of ecosystems
constituting unconnected meta-ecosystems. The ecosystem combinations are
into the objects unconnected_combinations_sets (Data >
Meta-ecosystems). We therefore compute a p-value for each unconnected
ecosystems combination, creating a p-value distribution. We keep as
p-value of the comparison the median of such distributions.
# --- ADD BASELINES --- #
baselines = ds_metaecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(system_nr,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- PREPARE TO COMPARE FULL, REDUCED, AND NULL MODEL WHILE RESHUFFLING ECOSYSTEM COMBINATIONS --- #
unconnected_combinations_sets_filtered = unconnected_combinations_sets %>%
filter(disturbance == disturbance_global_selected,
metaecosystem_type %in% metaecosystem_type_selected)
n_sets = unconnected_combinations_sets_filtered %>%
pull(set) %>%
max()
iterated_results_table = data.frame(Response = as.character(NA),
Levels = as.character(NA),
ΔAIC_full = NA,
p_full = NA,
ΔR2_full = NA,
ΔAIC_fix = NA,
p_fix = NA,
ΔR2_fix = NA,
combination_set = NA,
system_nr_unconnected_systems = as.character(NA)) %>%
slice(-1)
# --- COMPARE FULL, REDUCED, AND NULL MODEL WHILE RESHUFFLING ECOSYSTEM COMBINATIONS --- #
for (set_i in 1:n_sets) {
# Filter the data to contain all the connected meta-ecosystems and only a subset of unconnected meta-ecosystems
system_nr_unconnected_systems_selected = unconnected_combinations_sets_filtered %>%
filter(metaecosystem_type %in% metaecosystem_type_selected,
connection == "unconnected",
set == set_i) %>%
pull(system_nr)
filtered_data_2 = filtered_data %>%
filter(connection == "connected" |
(connection == "unconnected" &
system_nr %in% system_nr_unconnected_systems_selected))
# Construct models
full_model = try.different.optimizer.full.model()
reduced_model = try.different.optimizer.reduced.model()
null_model = try.different.optimizer.null.model()
# If all the optimisers fail, move on to the next iteration
if (is.null(full_model) || is.null(reduced_model) || is.null(null_model)) {
cat("This model could not be fitted with any optimiser. The unconnected meta-ecosystems in this iteration were:",
system_nr_unconnected_systems_selected,
"\n")
next
}
if(plot_model_residuals_metaecos == TRUE){
# Plot residuals - full model
print(qqnorm(resid(full_model))); print(qqline(resid(full_model)))
#full_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, full_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(full_model),
residuals = resid(full_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_full_model.png")),
plot = plot,
width = 8,
height = 6)
# Plot residuals - reduced model
print(qqnorm(resid(reduced_model))); print(qqline(resid(reduced_model)))
#reduced_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, reduced_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(reduced_model),
residuals = resid(reduced_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_reduced_model.png")),
plot = plot,
width = 8,
height = 6)
# Plot residuals - null model
print(qqnorm(resid(null_model))); print(qqline(resid(null_model)))
#null_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, null_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(null_model),
residuals = resid(null_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_null_model.png")),
plot = plot,
width = 8,
height = 6)
}
# Give model statistics
model_stats_full = compute.model.stats(full_model,
null_model,
"mixed_model")
model_stats_reduced = compute.model.stats(reduced_model,
null_model,
"mixed_model")
# Save model statistics
iterated_results_table = fill.results.table(iterated_results_table,
response_variable_selected,
metaecosystem_type_selected,
model_stats_full,
model_stats_reduced)
iterated_results_table$set[nrow(iterated_results_table)] = set_i
iterated_results_table$system_nr_unconnected_systems[nrow(iterated_results_table)] =
paste(system_nr_unconnected_systems_selected, collapse = " ")
}
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: optimx (L-BFGS-B)"
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: optimx (L-BFGS-B)"
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
Full vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
data.frame(deltaAIC = median(iterated_results_table$ΔAIC_full),
p_value = median(iterated_results_table$p_full),
R2 = NA) %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 2.7 0.522 none
# --- FULL VS NULL MODEL - SHOW ΔAIC & P VALUE DISTRIBUTIONS --- #
hist(iterated_results_table$ΔAIC_full, main = "Distribution of ΔAIC of the full model.")
hist(iterated_results_table$p_full, main = "Distribution of p-values of the full model.")
# --- FULL VS NULL MODEL - SHOW WHICH UNCONNECTED META-ECOSYSTEM NUMBER PRODUCD WHICH AIC --- #
iterated_results_table %>%
select(system_nr_unconnected_systems,
ΔAIC_full) %>%
arrange(ΔAIC_full)
## system_nr_unconnected_systems ΔAIC_full
## 1 1057 1062 -0.5222085
## 2 1062 1057 -0.5222085
## 3 1056 1064 0.3928216
## 4 1064 1056 0.3928216
## 5 1062 1063 0.6343763
## 6 1063 1062 0.6343763
## 7 1056 1065 0.8060701
## 8 1065 1056 0.8060701
## 9 1059 1060 0.8431111
## 10 1060 1059 0.8431111
## 11 1056 1063 2.1377348
## 12 1063 1056 2.1377348
## 13 1058 1064 2.3842720
## 14 1064 1058 2.3842720
## 15 1058 1060 2.6996423
## 16 1060 1058 2.6996423
## 17 1061 1064 2.7657309
## 18 1064 1061 2.7657309
## 19 1059 1063 2.8924317
## 20 1063 1059 2.8924317
## 21 1060 1065 3.1661120
## 22 1065 1060 3.1661120
## 23 1059 1061 3.2767665
## 24 1061 1059 3.2767665
## 25 1057 1065 3.3878827
## 26 1065 1057 3.3878827
## 27 1057 1061 3.3941129
## 28 1061 1057 3.3941129
## 29 1058 1062 3.7999873
## 30 1062 1058 3.7999873
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
data.frame(deltaAIC = median(iterated_results_table$ΔAIC_fix),
p_value = median(iterated_results_table$p_fix),
R2 = NA) %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 1.8 0.69 none
# --- REDUCED VS NULL MODEL - SHOW ΔAIC & P VALUE --- #
hist(iterated_results_table$ΔAIC_fix, main = "Distribution of ΔAIC of the reduced model.")
hist(iterated_results_table$p_fix, main = "Distribution of p-values of the reduced model.")
# --- REDUCED VS NULL MODEL - SHOW WHICH UNCONNECTED META-ECOSYSTEM NUMBER PRODUCD WHICH AIC --- #
iterated_results_table %>%
select(system_nr_unconnected_systems,
ΔAIC_fix) %>%
arrange(ΔAIC_fix)
## system_nr_unconnected_systems ΔAIC_fix
## 1 1059 1060 -0.5034275
## 2 1060 1059 -0.5034275
## 3 1058 1064 0.5100040
## 4 1064 1058 0.5100040
## 5 1056 1065 0.9744630
## 6 1065 1056 0.9744630
## 7 1058 1060 1.0064958
## 8 1060 1058 1.0064958
## 9 1059 1063 1.3234309
## 10 1063 1059 1.3234309
## 11 1060 1065 1.8267447
## 12 1065 1060 1.8267447
## 13 1057 1062 1.8395064
## 14 1062 1057 1.8395064
## 15 1056 1063 1.8412262
## 16 1063 1056 1.8412262
## 17 1062 1063 1.8589320
## 18 1063 1062 1.8589320
## 19 1057 1065 1.9234020
## 20 1065 1057 1.9234020
## 21 1056 1064 1.9605615
## 22 1064 1056 1.9605615
## 23 1058 1062 1.9782574
## 24 1062 1058 1.9782574
## 25 1061 1064 1.9883948
## 26 1064 1061 1.9883948
## 27 1059 1061 1.9910674
## 28 1061 1059 1.9910674
## 29 1057 1061 1.9997452
## 30 1061 1057 1.9997452
response_variable_selected = "total_metaecosystem_bioarea_mm2"
metaecosystem_type_selected = c("Medium-Medium",
"Small-Large")
Here we want to look at how this meta-ecosystem variable changed across time by plotting its mean ± 95 confidence interval:
plot.metaecos.points(ds_metaecosystems,
metaecosystem_type_selected,
connection_selected,
response_variable_selected)
plot.metaecos.replicates(ds_metaecosystems,
metaecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among meta-ecosystems. To make it easier to interpret differences, we decided to construct a model for each comparisons we are interested in, which are: SL (connected vs unconnected) and MM (connected vs unconnected).
metaecosystem_type_selected = c("Small-Large")
Our first step in the data analysis involves filtering the data to isolate the relevant data. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure we filtered data the right way.
# --- FILTER DATA --- #
filtered_data = ds_metaecosystems %>%
filter(time_point %in% time_points_model,
metaecosystem_type %in% metaecosystem_type_selected,
!is.na(!!sym("total_water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.metaecos.points(filtered_data,
metaecosystem_type_selected,
connection_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same meta-ecosystem on multiple occasions, we can develop mixed effect models to examine how the connection influenced this meta-ecosystem variable. To study the effects of connection we compare two models to a null model using ANOVA: a full model and a reduced model. In all models, we treat system nr as having a random effect on how the slope and intercept of the relationship between response variable and time, with the slope and intercept being correlated (Bates et al. 2015). We also include the total water that was added due to evaporation in the microwave and the time point before the first disturbance (baseline). In the syntax of lmer4 the three models look this this:
Full model = response_variable ~connection * scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Reduced model = response_variable ~connection + scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Null model = response_variable ~scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Unconnected meta-ecosystems are made of paired unconnected
ecosystems, which are paired randomly. However, how to pair unconnected
ecosystems can be done in multiple ways, as unconnected ecosystems did
not interact and therefore any combination between ecosystems would be
arbitrary. To make sure that the random combination we selected did not
bias our results, we run all the possible combinations of ecosystems
constituting unconnected meta-ecosystems. The ecosystem combinations are
into the objects unconnected_combinations_sets (Data >
Meta-ecosystems). We therefore compute a p-value for each unconnected
ecosystems combination, creating a p-value distribution. We keep as
p-value of the comparison the median of such distributions.
# --- ADD BASELINES --- #
baselines = ds_metaecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(system_nr,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- PREPARE TO COMPARE FULL, REDUCED, AND NULL MODEL WHILE RESHUFFLING ECOSYSTEM COMBINATIONS --- #
unconnected_combinations_sets_filtered = unconnected_combinations_sets %>%
filter(disturbance == disturbance_global_selected,
metaecosystem_type %in% metaecosystem_type_selected)
n_sets = unconnected_combinations_sets_filtered %>%
pull(set) %>%
max()
iterated_results_table = data.frame(Response = as.character(NA),
Levels = as.character(NA),
ΔAIC_full = NA,
p_full = NA,
ΔR2_full = NA,
ΔAIC_fix = NA,
p_fix = NA,
ΔR2_fix = NA,
combination_set = NA,
system_nr_unconnected_systems = as.character(NA)) %>%
slice(-1)
# --- COMPARE FULL, REDUCED, AND NULL MODEL WHILE RESHUFFLING ECOSYSTEM COMBINATIONS --- #
for (set_i in 1:n_sets) {
# Filter the data to contain all the connected meta-ecosystems and only a subset of unconnected meta-ecosystems
system_nr_unconnected_systems_selected = unconnected_combinations_sets_filtered %>%
filter(metaecosystem_type %in% metaecosystem_type_selected,
connection == "unconnected",
set == set_i) %>%
pull(system_nr)
filtered_data_2 = filtered_data %>%
filter(connection == "connected" |
(connection == "unconnected" &
system_nr %in% system_nr_unconnected_systems_selected))
# Construct models
full_model = try.different.optimizer.full.model()
reduced_model = try.different.optimizer.reduced.model()
null_model = try.different.optimizer.null.model()
# If all the optimisers fail, move on to the next iteration
if (is.null(full_model) || is.null(reduced_model) || is.null(null_model)) {
cat("This model could not be fitted with any optimiser. The unconnected meta-ecosystems in this iteration were:",
system_nr_unconnected_systems_selected,
"\n")
next
}
if(plot_model_residuals_metaecos == TRUE){
# Plot residuals - full model
print(qqnorm(resid(full_model))); print(qqline(resid(full_model)))
#full_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, full_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(full_model),
residuals = resid(full_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_full_model.png")),
plot = plot,
width = 8,
height = 6)
# Plot residuals - reduced model
print(qqnorm(resid(reduced_model))); print(qqline(resid(reduced_model)))
#reduced_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, reduced_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(reduced_model),
residuals = resid(reduced_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_reduced_model.png")),
plot = plot,
width = 8,
height = 6)
# Plot residuals - null model
print(qqnorm(resid(null_model))); print(qqline(resid(null_model)))
#null_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, null_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(null_model),
residuals = resid(null_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_null_model.png")),
plot = plot,
width = 8,
height = 6)
}
# Give model statistics
model_stats_full = compute.model.stats(full_model,
null_model,
"mixed_model")
model_stats_reduced = compute.model.stats(reduced_model,
null_model,
"mixed_model")
# Save model statistics
iterated_results_table = fill.results.table(iterated_results_table,
response_variable_selected,
metaecosystem_type_selected,
model_stats_full,
model_stats_reduced)
iterated_results_table$set[nrow(iterated_results_table)] = set_i
iterated_results_table$system_nr_unconnected_systems[nrow(iterated_results_table)] =
paste(system_nr_unconnected_systems_selected, collapse = " ")
}
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
Full vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
data.frame(deltaAIC = median(iterated_results_table$ΔAIC_full),
p_value = median(iterated_results_table$p_full),
R2 = NA) %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -4.7 0.013 ** moderate
# --- FULL VS NULL MODEL - SHOW ΔAIC & P VALUE DISTRIBUTIONS --- #
hist(iterated_results_table$ΔAIC_full, main = "Distribution of ΔAIC of the full model.")
hist(iterated_results_table$p_full, main = "Distribution of p-values of the full model.")
# --- FULL VS NULL MODEL - SHOW WHICH UNCONNECTED META-ECOSYSTEM NUMBER PRODUCD WHICH AIC --- #
iterated_results_table %>%
select(system_nr_unconnected_systems,
ΔAIC_full) %>%
arrange(ΔAIC_full)
## system_nr_unconnected_systems ΔAIC_full
## 1 1029 1035 1037 1043 -7.727533
## 2 1027 1035 1039 1043 -7.655432
## 3 1030 1034 1037 1043 -7.638735
## 4 1030 1032 1039 1043 -7.615971
## 5 1029 1032 1040 1043 -7.524050
## 6 1027 1034 1040 1043 -7.450471
## 7 1028 1035 1039 1042 -7.162399
## 8 1027 1034 1038 1045 -7.081832
## 9 1027 1033 1039 1045 -7.071848
## 10 1029 1033 1037 1045 -7.056631
## 11 1029 1035 1038 1042 -7.031460
## 12 1028 1034 1037 1045 -7.028276
## 13 1029 1032 1038 1045 -6.921750
## 14 1028 1032 1039 1045 -6.892323
## 15 1030 1034 1038 1042 -6.876597
## 16 1030 1033 1039 1042 -6.875019
## 17 1028 1034 1040 1042 -6.853147
## 18 1030 1033 1037 1044 -6.733186
## 19 1028 1035 1037 1044 -6.728381
## 20 1029 1033 1040 1042 -6.710949
## 21 1027 1035 1038 1044 -6.663780
## 22 1027 1033 1040 1044 -6.589870
## 23 1030 1032 1038 1044 -6.556158
## 24 1028 1032 1040 1044 -6.512095
## 25 1029 1033 1040 1041 -6.013323
## 26 1030 1033 1039 1041 -5.962450
## 27 1028 1034 1040 1041 -5.927921
## 28 1029 1031 1040 1043 -5.916268
## 29 1030 1031 1039 1043 -5.896132
## 30 1030 1034 1038 1041 -5.856540
## 31 1028 1035 1039 1041 -5.827911
## 32 1029 1035 1038 1041 -5.802513
## 33 1028 1031 1040 1044 -5.764537
## 34 1030 1031 1038 1044 -5.755838
## 35 1026 1034 1040 1043 -5.717678
## 36 1030 1034 1036 1043 -5.690262
## 37 1026 1035 1039 1043 -5.664849
## 38 1026 1033 1040 1044 -5.643699
## 39 1029 1035 1036 1043 -5.642307
## 40 1029 1031 1038 1045 -5.606113
## 41 1028 1031 1039 1045 -5.598127
## 42 1030 1033 1036 1044 -5.577949
## 43 1026 1035 1038 1044 -5.553605
## 44 1026 1033 1039 1045 -5.529081
## 45 1026 1034 1038 1045 -5.504414
## 46 1028 1035 1036 1044 -5.469466
## 47 1029 1033 1036 1045 -5.409531
## 48 1028 1034 1036 1045 -5.357912
## 49 1030 1034 1037 1041 -5.062180
## 50 1030 1032 1039 1041 -5.017348
## 51 1029 1035 1037 1041 -5.000258
## 52 1029 1031 1037 1043 -4.996980
## 53 1030 1031 1037 1043 -4.973116
## 54 1029 1033 1037 1041 -4.894467
## 55 1029 1032 1040 1041 -4.880863
## 56 1029 1032 1036 1043 -4.873366
## 57 1027 1031 1039 1043 -4.854814
## 58 1027 1035 1039 1041 -4.805687
## 59 1030 1032 1036 1043 -4.749263
## 60 1030 1031 1037 1044 -4.731349
## 61 1029 1032 1038 1041 -4.719383
## 62 1026 1032 1039 1043 -4.713433
## 63 1027 1034 1040 1041 -4.710236
## 64 1027 1031 1040 1043 -4.707615
## 65 1027 1034 1036 1043 -4.690867
## 66 1028 1034 1037 1041 -4.686533
## 67 1026 1034 1037 1043 -4.681340
## 68 1028 1032 1039 1041 -4.679637
## 69 1029 1031 1037 1045 -4.661082
## 70 1027 1033 1039 1041 -4.651398
## 71 1027 1031 1039 1045 -4.601990
## 72 1029 1032 1036 1045 -4.597869
## 73 1030 1033 1037 1041 -4.590071
## 74 1026 1034 1037 1045 -4.576498
## 75 1026 1032 1039 1045 -4.559471
## 76 1027 1034 1036 1045 -4.553361
## 77 1026 1035 1037 1043 -4.535289
## 78 1030 1032 1036 1044 -4.527942
## 79 1027 1035 1036 1043 -4.524292
## 80 1026 1032 1040 1043 -4.500114
## 81 1027 1031 1040 1044 -4.499237
## 82 1027 1034 1038 1041 -4.462135
## 83 1026 1035 1037 1044 -4.457465
## 84 1026 1035 1039 1042 -4.419120
## 85 1028 1031 1037 1044 -4.414189
## 86 1026 1032 1040 1044 -4.389336
## 87 1027 1035 1036 1044 -4.385321
## 88 1029 1035 1036 1042 -4.365671
## 89 1030 1031 1039 1042 -4.359016
## 90 1030 1032 1038 1041 -4.350854
## 91 1030 1034 1036 1042 -4.318791
## 92 1027 1031 1038 1044 -4.290546
## 93 1028 1032 1036 1044 -4.271462
## 94 1028 1035 1037 1041 -4.263758
## 95 1026 1033 1037 1044 -4.237185
## 96 1027 1033 1040 1041 -4.233578
## 97 1027 1033 1036 1044 -4.224832
## 98 1026 1034 1040 1042 -4.220221
## 99 1029 1031 1040 1042 -4.210273
## 100 1028 1031 1037 1045 -4.182755
## 101 1028 1032 1040 1041 -4.177853
## 102 1026 1032 1038 1044 -4.170816
## 103 1027 1031 1038 1045 -4.145132
## 104 1027 1033 1036 1045 -4.124827
## 105 1028 1032 1036 1045 -4.124631
## 106 1026 1033 1037 1045 -4.111620
## 107 1027 1035 1038 1041 -4.081721
## 108 1026 1032 1038 1045 -4.076579
## 109 1028 1031 1039 1042 -3.911105
## 110 1029 1031 1038 1042 -3.859186
## 111 1028 1034 1036 1042 -3.845004
## 112 1029 1033 1036 1042 -3.829989
## 113 1026 1033 1039 1042 -3.788824
## 114 1028 1035 1036 1042 -3.764522
## 115 1030 1031 1038 1042 -3.760138
## 116 1030 1033 1036 1042 -3.750804
## 117 1026 1034 1038 1042 -3.748107
## 118 1026 1035 1038 1042 -3.713061
## 119 1028 1031 1040 1042 -3.637594
## 120 1026 1033 1040 1042 -3.575222
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
data.frame(deltaAIC = median(iterated_results_table$ΔAIC_fix),
p_value = median(iterated_results_table$p_fix),
R2 = NA) %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -6 0.005 *** strong
# --- REDUCED VS NULL MODEL - SHOW ΔAIC & P VALUE --- #
hist(iterated_results_table$ΔAIC_fix, main = "Distribution of ΔAIC of the reduced model.")
hist(iterated_results_table$p_fix, main = "Distribution of p-values of the reduced model.")
# --- REDUCED VS NULL MODEL - SHOW WHICH UNCONNECTED META-ECOSYSTEM NUMBER PRODUCD WHICH AIC --- #
iterated_results_table %>%
select(system_nr_unconnected_systems,
ΔAIC_fix) %>%
arrange(ΔAIC_fix)
## system_nr_unconnected_systems ΔAIC_fix
## 1 1029 1035 1037 1043 -9.027495
## 2 1030 1032 1039 1043 -8.954782
## 3 1027 1035 1039 1043 -8.953645
## 4 1030 1034 1037 1043 -8.938494
## 5 1029 1032 1040 1043 -8.865605
## 6 1027 1034 1040 1043 -8.748882
## 7 1028 1035 1039 1042 -8.413385
## 8 1029 1035 1038 1042 -8.259577
## 9 1030 1034 1038 1042 -8.117274
## 10 1028 1034 1040 1042 -8.103648
## 11 1030 1033 1039 1042 -8.075007
## 12 1029 1033 1040 1042 -7.897270
## 13 1027 1033 1039 1045 -7.856135
## 14 1029 1033 1037 1045 -7.842151
## 15 1027 1034 1038 1045 -7.812198
## 16 1028 1034 1037 1045 -7.767698
## 17 1029 1032 1038 1045 -7.700232
## 18 1028 1032 1039 1045 -7.673330
## 19 1030 1033 1037 1044 -7.572265
## 20 1028 1035 1037 1044 -7.529811
## 21 1027 1035 1038 1044 -7.457289
## 22 1027 1033 1040 1044 -7.429258
## 23 1030 1032 1038 1044 -7.417826
## 24 1028 1032 1040 1044 -7.375357
## 25 1030 1034 1037 1041 -6.841704
## 26 1030 1032 1039 1041 -6.792714
## 27 1029 1035 1037 1041 -6.772735
## 28 1029 1032 1040 1041 -6.661884
## 29 1029 1031 1037 1043 -6.607156
## 30 1027 1035 1039 1041 -6.559464
## 31 1030 1031 1037 1043 -6.527950
## 32 1027 1034 1040 1041 -6.474666
## 33 1027 1031 1039 1043 -6.469146
## 34 1029 1032 1036 1043 -6.468622
## 35 1030 1031 1037 1044 -6.392601
## 36 1029 1033 1037 1041 -6.390550
## 37 1026 1032 1039 1043 -6.323662
## 38 1026 1034 1037 1043 -6.278530
## 39 1027 1034 1036 1043 -6.272061
## 40 1030 1032 1036 1043 -6.258909
## 41 1027 1031 1040 1043 -6.255766
## 42 1029 1031 1037 1045 -6.243618
## 43 1029 1032 1038 1041 -6.243000
## 44 1028 1032 1039 1041 -6.203860
## 45 1027 1031 1039 1045 -6.170342
## 46 1028 1034 1037 1041 -6.168347
## 47 1030 1032 1036 1044 -6.159701
## 48 1027 1033 1039 1041 -6.156933
## 49 1029 1032 1036 1045 -6.153424
## 50 1027 1031 1040 1044 -6.145366
## 51 1026 1034 1037 1045 -6.133999
## 52 1026 1035 1039 1042 -6.131506
## 53 1026 1032 1039 1045 -6.123051
## 54 1027 1034 1036 1045 -6.090519
## 55 1026 1035 1037 1044 -6.083119
## 56 1026 1035 1037 1043 -6.056636
## 57 1029 1035 1036 1042 -6.043273
## 58 1026 1032 1040 1043 -6.033521
## 59 1026 1032 1040 1044 -6.024460
## 60 1030 1031 1039 1042 -6.018103
## 61 1027 1035 1036 1043 -6.011887
## 62 1027 1035 1036 1044 -5.991941
## 63 1030 1034 1036 1042 -5.984961
## 64 1030 1033 1037 1041 -5.960607
## 65 1027 1034 1038 1041 -5.945592
## 66 1026 1034 1040 1042 -5.920984
## 67 1029 1031 1040 1042 -5.870160
## 68 1030 1032 1038 1041 -5.717625
## 69 1028 1031 1037 1044 -5.666819
## 70 1028 1035 1037 1041 -5.611263
## 71 1027 1033 1040 1041 -5.599949
## 72 1028 1032 1040 1041 -5.560828
## 73 1027 1031 1038 1044 -5.543873
## 74 1028 1032 1036 1044 -5.514031
## 75 1026 1033 1037 1044 -5.472128
## 76 1027 1033 1036 1044 -5.452803
## 77 1026 1032 1038 1044 -5.414863
## 78 1027 1035 1038 1041 -5.401754
## 79 1028 1031 1037 1045 -5.198517
## 80 1028 1031 1039 1042 -5.165071
## 81 1027 1031 1038 1045 -5.146500
## 82 1028 1032 1036 1045 -5.118095
## 83 1026 1033 1037 1045 -5.103040
## 84 1028 1034 1036 1042 -5.091830
## 85 1027 1033 1036 1045 -5.087943
## 86 1026 1032 1038 1045 -5.083316
## 87 1029 1031 1038 1042 -5.083172
## 88 1026 1033 1039 1042 -5.028630
## 89 1026 1034 1038 1042 -5.027497
## 90 1028 1035 1036 1042 -4.999759
## 91 1029 1033 1036 1042 -4.998900
## 92 1026 1035 1038 1042 -4.981652
## 93 1030 1031 1038 1042 -4.944673
## 94 1030 1033 1036 1042 -4.875355
## 95 1028 1031 1040 1042 -4.864438
## 96 1026 1033 1040 1042 -4.778558
## 97 1026 1035 1039 1043 -4.666146
## 98 1030 1031 1039 1043 -4.613930
## 99 1029 1031 1040 1043 -4.603233
## 100 1026 1034 1040 1043 -4.567046
## 101 1029 1035 1036 1043 -4.459418
## 102 1030 1034 1036 1043 -4.353283
## 103 1028 1035 1039 1041 -4.294022
## 104 1028 1034 1040 1041 -4.257623
## 105 1030 1033 1039 1041 -4.142899
## 106 1029 1033 1040 1041 -4.131670
## 107 1029 1035 1038 1041 -4.103028
## 108 1030 1034 1038 1041 -4.062398
## 109 1028 1031 1040 1044 -3.890159
## 110 1026 1035 1038 1044 -3.861817
## 111 1028 1035 1036 1044 -3.761767
## 112 1030 1031 1038 1044 -3.722197
## 113 1026 1033 1040 1044 -3.702216
## 114 1030 1033 1036 1044 -3.423312
## 115 1028 1031 1039 1045 -3.306349
## 116 1026 1034 1038 1045 -3.261318
## 117 1026 1033 1039 1045 -3.210635
## 118 1029 1031 1038 1045 -3.154647
## 119 1028 1034 1036 1045 -3.119564
## 120 1029 1033 1036 1045 -2.916396
metaecosystem_type_selected = c("Medium-Medium")
Our first step in the data analysis involves filtering the data to isolate the relevant data. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure we filtered data the right way.
# --- FILTER DATA --- #
filtered_data = ds_metaecosystems %>%
filter(time_point %in% time_points_model,
metaecosystem_type %in% metaecosystem_type_selected,
!is.na(!!sym("total_water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.metaecos.points(filtered_data,
metaecosystem_type_selected,
connection_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same meta-ecosystem on multiple occasions, we can develop mixed effect models to examine how the connection influenced this meta-ecosystem variable. To study the effects of connection we compare two models to a null model using ANOVA: a full model and a reduced model. In all models, we treat system nr as having a random effect on how the slope and intercept of the relationship between response variable and time, with the slope and intercept being correlated (Bates et al. 2015). We also include the total water that was added due to evaporation in the microwave and the time point before the first disturbance (baseline). In the syntax of lmer4 the three models look this this:
Full model = response_variable ~connection * scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Reduced model = response_variable ~connection + scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Null model = response_variable ~scale(day) + scale(total_water_addition_ml) * scale(day) + scale(baseline) * scale(day) + (day | system_nr)
Unconnected meta-ecosystems are made of paired unconnected
ecosystems, which are paired randomly. However, how to pair unconnected
ecosystems can be done in multiple ways, as unconnected ecosystems did
not interact and therefore any combination between ecosystems would be
arbitrary. To make sure that the random combination we selected did not
bias our results, we run all the possible combinations of ecosystems
constituting unconnected meta-ecosystems. The ecosystem combinations are
into the objects unconnected_combinations_sets (Data >
Meta-ecosystems). We therefore compute a p-value for each unconnected
ecosystems combination, creating a p-value distribution. We keep as
p-value of the comparison the median of such distributions.
# --- ADD BASELINES --- #
baselines = ds_metaecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(system_nr,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- PREPARE TO COMPARE FULL, REDUCED, AND NULL MODEL WHILE RESHUFFLING ECOSYSTEM COMBINATIONS --- #
unconnected_combinations_sets_filtered = unconnected_combinations_sets %>%
filter(disturbance == disturbance_global_selected,
metaecosystem_type %in% metaecosystem_type_selected)
n_sets = unconnected_combinations_sets_filtered %>%
pull(set) %>%
max()
iterated_results_table = data.frame(Response = as.character(NA),
Levels = as.character(NA),
ΔAIC_full = NA,
p_full = NA,
ΔR2_full = NA,
ΔAIC_fix = NA,
p_fix = NA,
ΔR2_fix = NA,
combination_set = NA,
system_nr_unconnected_systems = as.character(NA)) %>%
slice(-1)
# --- COMPARE FULL, REDUCED, AND NULL MODEL WHILE RESHUFFLING ECOSYSTEM COMBINATIONS --- #
for (set_i in 1:n_sets) {
# Filter the data to contain all the connected meta-ecosystems and only a subset of unconnected meta-ecosystems
system_nr_unconnected_systems_selected = unconnected_combinations_sets_filtered %>%
filter(metaecosystem_type %in% metaecosystem_type_selected,
connection == "unconnected",
set == set_i) %>%
pull(system_nr)
filtered_data_2 = filtered_data %>%
filter(connection == "connected" |
(connection == "unconnected" &
system_nr %in% system_nr_unconnected_systems_selected))
# Construct models
full_model = try.different.optimizer.full.model()
reduced_model = try.different.optimizer.reduced.model()
null_model = try.different.optimizer.null.model()
# If all the optimisers fail, move on to the next iteration
if (is.null(full_model) || is.null(reduced_model) || is.null(null_model)) {
cat("This model could not be fitted with any optimiser. The unconnected meta-ecosystems in this iteration were:",
system_nr_unconnected_systems_selected,
"\n")
next
}
if(plot_model_residuals_metaecos == TRUE){
# Plot residuals - full model
print(qqnorm(resid(full_model))); print(qqline(resid(full_model)))
#full_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, full_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(full_model),
residuals = resid(full_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_full_model.png")),
plot = plot,
width = 8,
height = 6)
# Plot residuals - reduced model
print(qqnorm(resid(reduced_model))); print(qqline(resid(reduced_model)))
#reduced_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, reduced_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(reduced_model),
residuals = resid(reduced_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_reduced_model.png")),
plot = plot,
width = 8,
height = 6)
# Plot residuals - null model
print(qqnorm(resid(null_model))); print(qqline(resid(null_model)))
#null_model_res_vs_fit[[set_i]] = create.res.vs.fit.metaecos(filtered_data_2, null_model)
plot = filtered_data_2 %>%
mutate(predicted = fitted(null_model),
residuals = resid(null_model)) %>%
ggplot(aes(x = predicted,
y = residuals)) +
geom_point()
ggsave(here("6_results",
"residual_plots",
paste0(disturbance_global_selected,
"_disturbance_",
gsub(pattern = " ", replacement = "", metaecosystem_type_selected[[1]]),
"_",
response_variable_selected,
"_",
set_i,
"_null_model.png")),
plot = plot,
width = 8,
height = 6)
}
# Give model statistics
model_stats_full = compute.model.stats(full_model,
null_model,
"mixed_model")
model_stats_reduced = compute.model.stats(reduced_model,
null_model,
"mixed_model")
# Save model statistics
iterated_results_table = fill.results.table(iterated_results_table,
response_variable_selected,
metaecosystem_type_selected,
model_stats_full,
model_stats_reduced)
iterated_results_table$set[nrow(iterated_results_table)] = set_i
iterated_results_table$system_nr_unconnected_systems[nrow(iterated_results_table)] =
paste(system_nr_unconnected_systems_selected, collapse = " ")
}
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: optimx (L-BFGS-B)"
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: optimx (L-BFGS-B)"
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
## [1] "Model successfully fitted with optimizer: bobyqa "
Full vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
data.frame(deltaAIC = median(iterated_results_table$ΔAIC_full),
p_value = median(iterated_results_table$p_full),
R2 = NA) %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 3.3 0.705 none
# --- FULL VS NULL MODEL - SHOW ΔAIC & P VALUE DISTRIBUTIONS --- #
hist(iterated_results_table$ΔAIC_full, main = "Distribution of ΔAIC of the full model.")
hist(iterated_results_table$p_full, main = "Distribution of p-values of the full model.")
# --- FULL VS NULL MODEL - SHOW WHICH UNCONNECTED META-ECOSYSTEM NUMBER PRODUCD WHICH AIC --- #
iterated_results_table %>%
select(system_nr_unconnected_systems,
ΔAIC_full) %>%
arrange(ΔAIC_full)
## system_nr_unconnected_systems ΔAIC_full
## 1 1056 1065 1.441922
## 2 1065 1056 1.441922
## 3 1059 1061 1.511884
## 4 1061 1059 1.511884
## 5 1058 1062 1.523226
## 6 1062 1058 1.523226
## 7 1058 1060 2.965093
## 8 1060 1058 2.965093
## 9 1057 1061 3.058813
## 10 1061 1057 3.058813
## 11 1056 1063 3.228377
## 12 1063 1056 3.228377
## 13 1058 1064 3.278592
## 14 1064 1058 3.278592
## 15 1057 1065 3.300185
## 16 1065 1057 3.300185
## 17 1059 1063 3.413017
## 18 1063 1059 3.413017
## 19 1060 1065 3.536934
## 20 1065 1060 3.536934
## 21 1061 1064 3.566875
## 22 1064 1061 3.566875
## 23 1062 1063 3.603087
## 24 1063 1062 3.603087
## 25 1059 1060 3.720156
## 26 1060 1059 3.720156
## 27 1057 1062 3.834042
## 28 1062 1057 3.834042
## 29 1056 1064 3.836198
## 30 1064 1056 3.836198
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
data.frame(deltaAIC = median(iterated_results_table$ΔAIC_fix),
p_value = median(iterated_results_table$p_fix),
R2 = NA) %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 2 0.918 none
# --- REDUCED VS NULL MODEL - SHOW ΔAIC & P VALUE --- #
hist(iterated_results_table$ΔAIC_fix, main = "Distribution of ΔAIC of the reduced model.")
hist(iterated_results_table$p_fix, main = "Distribution of p-values of the reduced model.")
# --- REDUCED VS NULL MODEL - SHOW WHICH UNCONNECTED META-ECOSYSTEM NUMBER PRODUCD WHICH AIC --- #
iterated_results_table %>%
select(system_nr_unconnected_systems,
ΔAIC_fix) %>%
arrange(ΔAIC_fix)
## system_nr_unconnected_systems ΔAIC_fix
## 1 1056 1065 0.4846993
## 2 1065 1056 0.4846993
## 3 1058 1062 0.5732773
## 4 1062 1058 0.5732773
## 5 1059 1061 0.6336872
## 6 1061 1059 0.6336872
## 7 1056 1063 1.8349450
## 8 1063 1056 1.8349450
## 9 1062 1063 1.8795317
## 10 1063 1062 1.8795317
## 11 1059 1063 1.9620763
## 12 1063 1059 1.9620763
## 13 1058 1060 1.9647601
## 14 1060 1058 1.9647601
## 15 1061 1064 1.9894475
## 16 1064 1061 1.9894475
## 17 1057 1061 1.9898886
## 18 1061 1057 1.9898886
## 19 1057 1065 1.9936749
## 20 1065 1057 1.9936749
## 21 1059 1060 1.9941971
## 22 1060 1059 1.9941971
## 23 1058 1064 1.9976605
## 24 1064 1058 1.9976605
## 25 1060 1065 1.9985652
## 26 1065 1060 1.9985652
## 27 1057 1062 1.9988504
## 28 1062 1057 1.9988504
## 29 1056 1064 1.9996285
## 30 1064 1056 1.9996285
ecosystem_type_selected = c("Small unconnected",
"Medium unconnected",
"Large unconnected",
"Small connected to small",
"Small connected to large",
"Medium connected to medium",
"Large connected to small",
"Large connected to large")
ds_ecosystems %>%
filter(is.na(species_richness) != TRUE) %>%
ggplot(aes(x = species_richness,
y = bioarea_mm2_per_ml)) +
geom_point() +
xlim(0, length(protist_species)) +
labs(x = axis_names$axis_name[axis_names$variable == "species_richness"],
y = axis_names$axis_name[axis_names$variable == "bioarea_mm2_per_ml"]) +
theme_bw() +
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
legend.position = legend_position,
legend.key.width = unit(legend_width_cm, "cm"))
ds_ecosystems %>%
filter(is.na(shannon) != TRUE) %>%
ggplot(aes(x = shannon,
y = bioarea_mm2_per_ml)) +
geom_point() +
labs(x = axis_names$axis_name[axis_names$variable == "shannon"],
y = axis_names$axis_name[axis_names$variable == "bioarea_mm2_per_ml"]) +
theme_bw() +
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
legend.position = legend_position,
legend.key.width = unit(legend_width_cm, "cm"))
ds_ecosystems %>%
filter(is.na(evenness_pielou) != TRUE) %>%
ggplot(aes(x = evenness_pielou,
y = bioarea_mm2_per_ml)) +
geom_point() +
labs(x = axis_names$axis_name[axis_names$variable == "evenness_pielou"],
y = axis_names$axis_name[axis_names$variable == "bioarea_mm2_per_ml"]) +
theme_bw() +
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
legend.position = legend_position,
legend.key.width = unit(legend_width_cm, "cm"))
response_variable_selected = "water_addition_ml"
UNLIKE ALL THE OTHER ANALYSIS, THIS INCLUDES BOTH DISTURBANCE LEVELS.
We want to know whether the size of an ecosystem influenced its evaporation rate. We first start from plotting how the water that was added to the cultures changed across size through its mean ± 95 confidence interval:
# --- FILTER DATASET --- #
ds_ecosystems_both_disturbances_filtered = ds_ecosystems_both_disturbances %>%
filter(!is.na(water_addition_ml)) %>%
mutate(sqrt_water_addition_ml = sqrt(water_addition_ml),
log_water_addition_ml = log(water_addition_ml),
inv_water_addition_ml = 1 / water_addition_ml)
# --- PLOT WATER ADDITION MEAN ± 95 CI --- #
ds_ecosystems_both_disturbances_filtered %>%
summarySE(measurevar = response_variable_selected,
groupvars = c("day", "ecosystem_size")) %>%
ggplot(aes(x = day,
y = get(response_variable_selected),
group = interaction(day, ecosystem_size),
color = ecosystem_size)) +
geom_point(stat = "summary",
fun = "mean",
position = position_dodge(dodging),
size = treatment_points_size) +
geom_line(stat = "summary",
fun = "mean",
aes(group = ecosystem_size),
position = position_dodge(dodging),
linewidth = treatment_lines_linewidth) +
geom_errorbar(aes(ymax = get(response_variable_selected) + ci,
ymin = get(response_variable_selected) - ci),
width = width_errorbar,
position = position_dodge(dodging)) +
labs(x = "Day",
y = "Water addition (ml)",
color = "") +
scale_x_continuous(breaks = unique(ds_ecosystems$day)) +
geom_vline(xintercept = resource_flow_days,
linetype = resource_flow_line_type,
color = resource_flow_line_colour,
linewidth = resource_flow_line_width) +
theme_bw() +
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
legend.position = legend_position) +
scale_color_manual(values = c("#000000", "#737373", "#bdbdbd")) +
geom_rect(xmin = grey_background_xmin,
xmax = grey_background_xmax,
ymin = grey_background_ymin,
ymax = grey_background_ymax,
fill = grey_background_fill,
alpha = grey_background_alpha,
color = grey_background_color)
# --- PLOT WATER ADDITION SINGLE REPLICATES --- #
ds_ecosystems_both_disturbances_filtered %>%
ggplot(aes(x = day,
y = get(response_variable_selected),
group = interaction(culture_ID, day),
color = ecosystem_size)) +
geom_point() +
geom_line(aes(group = culture_ID)) +
scale_x_continuous(breaks = unique(ds_ecosystems$day)) +
theme_bw() +
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
legend.position = legend_position) +
geom_rect(xmin = grey_background_xmin,
xmax = grey_background_xmax,
ymin = grey_background_ymin,
ymax = grey_background_ymax,
fill = grey_background_fill,
alpha = grey_background_alpha,
color = grey_background_color) +
labs(x = "Day",
y = "Water addition (ml)",
color = "") +
scale_color_manual(values = c("#000000", "#737373", "#bdbdbd"))
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_size +
(1 | time_point),
data = ds_ecosystems_both_disturbances_filtered,
REML = FALSE)
null_model = lmer(get(response_variable_selected) ~
(1 | time_point),
data = ds_ecosystems_both_disturbances_filtered,
REML = FALSE)
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
print()
## deltaAIC p_value R2
## 1 -4.690089 0.01297093 NA
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_size + (1 | time_point)
## Data: ds_ecosystems_both_disturbances_filtered
##
## AIC BIC logLik deviance df.resid
## 748.4 769.9 -369.2 738.4 538
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -3.8 -0.7 0.1 0.4 4.5
##
## Random effects:
## Groups Name Variance Std.Dev.
## time_point (Intercept) 0.2 0.4
## Residual 0.2 0.5
## Number of obs: 543, groups: time_point, 5
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 1.63 0.20 5.18 8 4e-04 ***
## ecosystem_sizeMedium -0.13 0.05 538.00 -3 0.009 **
## ecosystem_sizeSmall -0.12 0.05 538.00 -2 0.015 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecsy_M
## ecsystm_szM -0.109
## ecsystm_szS -0.117 0.459
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(ds_ecosystems_both_disturbances_filtered, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
response_variable_selected = "shannon"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT MEAN ± 95% CI --- #
"High disturbance"
## [1] "High disturbance"
plot.all.patches.points(data = ds_ecosystems_both_disturbances %>% filter(disturbance == "high"),
response_variable_selected)
## Warning in qt(conf.interval/2 + 0.5, datac$N - 1): NaNs produced
"Low disturbance"
## [1] "Low disturbance"
plot.all.patches.points(data = ds_ecosystems_both_disturbances %>% filter(disturbance == "low"),
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. To do so, we go through the following steps.
# --- ADD BASELINES --- #
baselines = ds_ecosystems_both_disturbances %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
data_for_analysis = ds_ecosystems_both_disturbances %>%
left_join(baselines)
# --- FILTER DATA AND CHANGE THE NAME OF LEVELS --- #
data_for_analysis = data_for_analysis %>%
filter(time_point %in% time_points_model,
!is.na(!!sym(response_variable_selected)),
!is.na(water_addition_ml)) %>%
mutate(ecosystem_type = case_when(ecosystem_type == "Small unconnected" ~ "S",
ecosystem_type == "Medium unconnected" ~ "M",
ecosystem_type == "Large unconnected" ~ "L",
ecosystem_type == "Small connected to small" ~ "S_S",
ecosystem_type == "Small connected to large" ~ "S_L",
ecosystem_type == "Medium connected to medium" ~ "M_M",
ecosystem_type == "Large connected to large" ~ "L_L",
ecosystem_type == "Large connected to small" ~ "L_S",
TRUE ~ ecosystem_type))
# --- ADD EVAPORATION RATES RESIDUALS --- #
evaporation_model = lm(get(response_variable_selected) ~
ecosystem_type * disturbance * day +
baseline * day,
data = data_for_analysis)
par(mfrow = c(2, 2))
plot(evaporation_model)
data_for_analysis = data_for_analysis %>%
mutate(evaporation_residuals = residuals(evaporation_model))
# --- PLOT MEAN ± 95% CI OF FILTERED DATA --- #
"High disturbance"
## [1] "High disturbance"
plot.all.patches.points(data = data_for_analysis %>% filter(disturbance == "high"),
response_variable_selected)
"Low disturbance"
## [1] "Low disturbance"
plot.all.patches.points(data = data_for_analysis %>% filter(disturbance == "low"),
response_variable_selected)
# --- CHECK COLLINEARITY --- #
# # Select the relevant numeric columns (ensure that they are numeric)
# numeric_data <- data_for_analysis %>%
# select(day, water_addition_ml, baseline)
#
# # Calculate the correlation matrix
# cor_matrix <- cor(numeric_data, use = "complete.obs")
#
# # Use corrplot to visualize the correlation matrix
# corrplot::corrplot(cor_matrix, method = 'number')
# --- CONSTRUCT MODEL --- #
# full_model = lmer(get(response_variable_selected) ~
# ecosystem_type * disturbance * day +
# water_addition_ml * day +
# baseline * day +
# (day | culture_ID),
# data = data_for_analysis,
# REML = FALSE)
full_model <- glmmTMB(get(response_variable_selected) ~
ecosystem_type * disturbance * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = data_for_analysis,
family = tweedie(link = "log"),
control = glmmTMBControl(optimizer = "optim"))
## Warning in finalizeTMB(TMBStruc, obj, fit, h, data.tmb.old): Model convergence
## problem; non-positive-definite Hessian matrix. See vignette('troubleshooting')
## Warning in finalizeTMB(TMBStruc, obj, fit, h, data.tmb.old): Model convergence
## problem; . See vignette('troubleshooting'), help('diagnose')
# --- SHOW MODEL SUMMARY --- #
print(summary(full_model), digits = 1)
## Warning in sqrt(diag(vcovs)): NaNs produced
## Family: tweedie ( log )
## Formula:
## get(response_variable_selected) ~ ecosystem_type * disturbance *
## scale(day) + scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: data_for_analysis
##
## AIC BIC logLik deviance df.resid
## NA NA NA NA 489
##
## Random effects:
##
## Conditional model:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 0.7 0.8
## day 0.7 0.9 0.17
## Number of obs: 530, groups: culture_ID, 109
##
## Dispersion parameter for tweedie family (): 0.459
##
## Conditional model:
## Estimate Std. Error z value
## (Intercept) 0.049 7.726 0.0
## ecosystem_typeL_L 0.070 9.375 0.0
## ecosystem_typeL_S 0.008 10.807 0.0
## ecosystem_typeM 0.020 10.890 0.0
## ecosystem_typeM_M 0.065 9.342 0.0
## ecosystem_typeS 0.066 NaN NaN
## ecosystem_typeS_L 0.069 6.705 0.0
## ecosystem_typeS_S 0.064 NaN NaN
## disturbancelow 0.071 10.658 0.0
## scale(day) -0.010 2.172 0.0
## scale(water_addition_ml) 0.056 0.051 1.1
## scale(baseline) 0.054 1.381 0.0
## ecosystem_typeL_L:disturbancelow 0.061 13.222 0.0
## ecosystem_typeL_S:disturbancelow 0.138 15.089 0.0
## ecosystem_typeM:disturbancelow -0.026 14.632 0.0
## ecosystem_typeM_M:disturbancelow 0.024 12.999 0.0
## ecosystem_typeS:disturbancelow 0.049 1.436 0.0
## ecosystem_typeS_L:disturbancelow -0.105 11.318 0.0
## ecosystem_typeS_S:disturbancelow 0.056 10.417 0.0
## ecosystem_typeL_L:scale(day) 0.035 2.636 0.0
## ecosystem_typeL_S:scale(day) -0.022 3.039 0.0
## ecosystem_typeM:scale(day) -0.039 3.062 0.0
## ecosystem_typeM_M:scale(day) 0.039 2.627 0.0
## ecosystem_typeS:scale(day) 0.070 NaN NaN
## ecosystem_typeS_L:scale(day) 0.040 1.868 0.0
## ecosystem_typeS_S:scale(day) -0.055 NaN NaN
## disturbancelow:scale(day) -0.013 2.996 0.0
## scale(day):scale(water_addition_ml) 0.020 0.047 0.4
## scale(day):scale(baseline) 0.059 0.386 0.2
## ecosystem_typeL_L:disturbancelow:scale(day) 0.074 3.718 0.0
## ecosystem_typeL_S:disturbancelow:scale(day) -0.008 4.241 0.0
## ecosystem_typeM:disturbancelow:scale(day) 0.031 4.111 0.0
## ecosystem_typeM_M:disturbancelow:scale(day) 0.031 3.654 0.0
## ecosystem_typeS:disturbancelow:scale(day) 0.044 0.774 0.1
## ecosystem_typeS_L:disturbancelow:scale(day) -0.059 3.167 0.0
## ecosystem_typeS_S:disturbancelow:scale(day) 0.064 2.922 0.0
## Pr(>|z|)
## (Intercept) 1.0
## ecosystem_typeL_L 1.0
## ecosystem_typeL_S 1.0
## ecosystem_typeM 1.0
## ecosystem_typeM_M 1.0
## ecosystem_typeS NaN
## ecosystem_typeS_L 1.0
## ecosystem_typeS_S NaN
## disturbancelow 1.0
## scale(day) 1.0
## scale(water_addition_ml) 0.3
## scale(baseline) 1.0
## ecosystem_typeL_L:disturbancelow 1.0
## ecosystem_typeL_S:disturbancelow 1.0
## ecosystem_typeM:disturbancelow 1.0
## ecosystem_typeM_M:disturbancelow 1.0
## ecosystem_typeS:disturbancelow 1.0
## ecosystem_typeS_L:disturbancelow 1.0
## ecosystem_typeS_S:disturbancelow 1.0
## ecosystem_typeL_L:scale(day) 1.0
## ecosystem_typeL_S:scale(day) 1.0
## ecosystem_typeM:scale(day) 1.0
## ecosystem_typeM_M:scale(day) 1.0
## ecosystem_typeS:scale(day) NaN
## ecosystem_typeS_L:scale(day) 1.0
## ecosystem_typeS_S:scale(day) NaN
## disturbancelow:scale(day) 1.0
## scale(day):scale(water_addition_ml) 0.7
## scale(day):scale(baseline) 0.9
## ecosystem_typeL_L:disturbancelow:scale(day) 1.0
## ecosystem_typeL_S:disturbancelow:scale(day) 1.0
## ecosystem_typeM:disturbancelow:scale(day) 1.0
## ecosystem_typeM_M:disturbancelow:scale(day) 1.0
## ecosystem_typeS:disturbancelow:scale(day) 1.0
## ecosystem_typeS_L:disturbancelow:scale(day) 1.0
## ecosystem_typeS_S:disturbancelow:scale(day) 1.0
# --- RUN ANOVA --- #
car::Anova(full_model, type = "III")
## Analysis of Deviance Table (Type III Wald chisquare tests)
##
## Response: get(response_variable_selected)
## Chisq Df Pr(>Chisq)
## (Intercept) 0.0000 1 0.9949
## ecosystem_type 0.0001 7 1.0000
## disturbance 0.0000 1 0.9947
## scale(day) 0.0000 1 0.9962
## scale(water_addition_ml) 1.2133 1 0.2707
## scale(baseline) 0.0015 1 0.9688
## ecosystem_type:disturbance 0.0003 7 1.0000
## ecosystem_type:scale(day) 0.0039 7 1.0000
## disturbance:scale(day) 0.0000 1 0.9966
## scale(day):scale(water_addition_ml) 0.1868 1 0.6656
## scale(day):scale(baseline) 0.0231 1 0.8792
## ecosystem_type:disturbance:scale(day) 0.0017 7 1.0000
# --- GET ECOSYSTEM TYPE CONSTRASTS --- #
emmeans_output = emmeans(full_model,
specs = pairwise ~ ecosystem_type * disturbance,
adjust = "tukey",
bias.adj = TRUE,
lmer.df = "satterthwaite")
emmeans_output
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## Warning in .qf.non0(object@V, x): Negative variance estimate obtained!
## $emmeans
## ecosystem_type disturbance emmean SE df asymp.LCL asymp.UCL
## L high 0.0494 7.73 Inf -15.09 15.19
## L_L high 0.1197 5.42 Inf -10.51 10.75
## L_S high 0.0570 7.66 Inf -14.96 15.07
## M high 0.0690 7.66 Inf -14.94 15.07
## M_M high 0.1145 5.48 Inf -10.62 10.85
## S high 0.1157 NaN Inf NaN NaN
## S_L high 0.1182 NaN Inf NaN NaN
## S_S high 0.1130 NaN Inf NaN NaN
## L low 0.1203 7.64 Inf -14.84 15.08
## L_L low 0.2520 5.32 Inf -10.17 10.67
## L_S low 0.2662 7.25 Inf -13.95 14.48
## M low 0.1137 7.20 Inf -14.01 14.23
## M_M low 0.2096 5.48 Inf -10.54 10.96
## S low 0.2361 5.42 Inf -10.38 10.85
## S_L low 0.0839 7.80 Inf -15.21 15.38
## S_S low 0.2395 4.20 Inf -7.99 8.47
##
## Results are given on the log (not the response) scale.
## Confidence level used: 0.95
##
## $contrasts
## contrast estimate SE df z.ratio p.value
## L high - L_L high -0.070344 9.38 Inf -0.008 1.0000
## L high - L_S high -0.007617 10.81 Inf -0.001 1.0000
## L high - M high -0.019654 10.89 Inf -0.002 1.0000
## L high - M_M high -0.065118 9.34 Inf -0.007 1.0000
## L high - S high -0.066334 NaN Inf NaN NaN
## L high - S_L high -0.068784 6.70 Inf -0.010 1.0000
## L high - S_S high -0.063653 NaN Inf NaN NaN
## L high - L low -0.070903 10.66 Inf -0.007 1.0000
## L high - L_L low -0.202587 9.26 Inf -0.022 1.0000
## L high - L_S low -0.216819 10.78 Inf -0.020 1.0000
## L high - M low -0.064341 10.67 Inf -0.006 1.0000
## L high - M_M low -0.160174 9.38 Inf -0.017 1.0000
## L high - S low -0.186673 9.20 Inf -0.020 1.0000
## L high - S_L low -0.034558 11.15 Inf -0.003 1.0000
## L high - S_S low -0.190097 8.53 Inf -0.022 1.0000
## L_L high - L_S high 0.062727 9.30 Inf 0.007 1.0000
## L_L high - M high 0.050689 9.39 Inf 0.005 1.0000
## L_L high - M_M high 0.005226 7.67 Inf 0.001 1.0000
## L_L high - S high 0.004010 NaN Inf NaN NaN
## L_L high - S_L high 0.001559 5.01 Inf 0.000 1.0000
## L_L high - S_S high 0.006691 NaN Inf NaN NaN
## L_L high - L low -0.000559 9.34 Inf 0.000 1.0000
## L_L high - L_L low -0.132243 7.61 Inf -0.017 1.0000
## L_L high - L_S low -0.146475 9.02 Inf -0.016 1.0000
## L_L high - M low 0.006003 8.94 Inf 0.001 1.0000
## L_L high - M_M low -0.089830 7.65 Inf -0.012 1.0000
## L_L high - S low -0.116329 7.86 Inf -0.015 1.0000
## L_L high - S_L low 0.035785 9.59 Inf 0.004 1.0000
## L_L high - S_S low -0.119753 6.94 Inf -0.017 1.0000
## L_S high - M high -0.012038 10.84 Inf -0.001 1.0000
## L_S high - M_M high -0.057501 9.26 Inf -0.006 1.0000
## L_S high - S high -0.058717 NaN Inf NaN NaN
## L_S high - S_L high -0.061168 5.71 Inf -0.011 1.0000
## L_S high - S_S high -0.056036 NaN Inf NaN NaN
## L_S high - L low -0.063286 10.51 Inf -0.006 1.0000
## L_S high - L_L low -0.194970 9.12 Inf -0.021 1.0000
## L_S high - L_S low -0.209202 10.89 Inf -0.019 1.0000
## L_S high - M low -0.056724 10.79 Inf -0.005 1.0000
## L_S high - M_M low -0.152557 9.34 Inf -0.016 1.0000
## L_S high - S low -0.179056 8.74 Inf -0.020 1.0000
## L_S high - S_L low -0.026942 11.11 Inf -0.002 1.0000
## L_S high - S_S low -0.182480 8.19 Inf -0.022 1.0000
## M high - M_M high -0.045463 9.43 Inf -0.005 1.0000
## M high - S high -0.046679 NaN Inf NaN NaN
## M high - S_L high -0.049130 6.98 Inf -0.007 1.0000
## M high - S_S high -0.043998 NaN Inf NaN NaN
## M high - L low -0.051249 10.83 Inf -0.005 1.0000
## M high - L_L low -0.182933 9.33 Inf -0.020 1.0000
## M high - L_S low -0.197165 10.54 Inf -0.019 1.0000
## M high - M low -0.044687 10.52 Inf -0.004 1.0000
## M high - M_M low -0.140520 9.43 Inf -0.015 1.0000
## M high - S low -0.167018 9.36 Inf -0.018 1.0000
## M high - S_L low -0.014904 10.93 Inf -0.001 1.0000
## M high - S_S low -0.170442 8.73 Inf -0.020 1.0000
## M_M high - S high -0.001216 NaN Inf NaN NaN
## M_M high - S_L high -0.003667 5.38 Inf -0.001 1.0000
## M_M high - S_S high 0.001465 NaN Inf NaN NaN
## M_M high - L low -0.005785 9.33 Inf -0.001 1.0000
## M_M high - L_L low -0.137469 7.63 Inf -0.018 1.0000
## M_M high - L_S low -0.151701 9.05 Inf -0.017 1.0000
## M_M high - M low 0.000777 8.93 Inf 0.000 1.0000
## M_M high - M_M low -0.095056 7.62 Inf -0.012 1.0000
## M_M high - S low -0.121555 8.01 Inf -0.015 1.0000
## M_M high - S_L low 0.030559 9.69 Inf 0.003 1.0000
## M_M high - S_S low -0.124979 7.01 Inf -0.018 1.0000
## S high - S_L high -0.002451 4.43 Inf -0.001 1.0000
## S high - S_S high 0.002681 3.90 Inf 0.001 1.0000
## S high - L low -0.004569 NaN Inf NaN NaN
## S high - L_L low -0.136253 NaN Inf NaN NaN
## S high - L_S low -0.150485 NaN Inf NaN NaN
## S high - M low 0.001993 NaN Inf NaN NaN
## S high - M_M low -0.093840 NaN Inf NaN NaN
## S high - S low -0.120339 NaN Inf NaN NaN
## S high - S_L low 0.031775 NaN Inf NaN NaN
## S high - S_S low -0.123763 NaN Inf NaN NaN
## S_L high - S_S high 0.005132 9.33 Inf 0.001 1.0000
## S_L high - L low -0.002119 8.73 Inf 0.000 1.0000
## S_L high - L_L low -0.133802 6.22 Inf -0.022 1.0000
## S_L high - L_S low -0.148035 NaN Inf NaN NaN
## S_L high - M low 0.004444 NaN Inf NaN NaN
## S_L high - M_M low -0.091390 4.17 Inf -0.022 1.0000
## S_L high - S low -0.117888 10.46 Inf -0.011 1.0000
## S_L high - S_L low 0.034226 6.83 Inf 0.005 1.0000
## S_L high - S_S low -0.121312 8.18 Inf -0.015 1.0000
## S_S high - L low -0.007250 4.54 Inf -0.002 1.0000
## S_S high - L_L low -0.138934 NaN Inf NaN NaN
## S_S high - L_S low -0.153166 NaN Inf NaN NaN
## S_S high - M low -0.000688 NaN Inf NaN NaN
## S_S high - M_M low -0.096521 NaN Inf NaN NaN
## S_S high - S low -0.123020 8.33 Inf -0.015 1.0000
## S_S high - S_L low 0.029095 NaN Inf NaN NaN
## S_S high - S_S low -0.126444 4.40 Inf -0.029 1.0000
## L low - L_L low -0.131684 9.41 Inf -0.014 1.0000
## L low - L_S low -0.145916 10.26 Inf -0.014 1.0000
## L low - M low 0.006562 10.12 Inf 0.001 1.0000
## L low - M_M low -0.089271 9.21 Inf -0.010 1.0000
## L low - S low -0.115770 10.22 Inf -0.011 1.0000
## L low - S_L low 0.036345 11.11 Inf 0.003 1.0000
## L low - S_S low -0.119194 9.19 Inf -0.013 1.0000
## L_L low - L_S low -0.014232 8.70 Inf -0.002 1.0000
## L_L low - M low 0.138246 8.62 Inf 0.016 1.0000
## L_L low - M_M low 0.042413 7.53 Inf 0.006 1.0000
## L_L low - S low 0.015914 8.38 Inf 0.002 1.0000
## L_L low - S_L low 0.168029 9.52 Inf 0.018 1.0000
## L_L low - S_S low 0.012490 7.29 Inf 0.002 1.0000
## L_S low - M low 0.152478 10.85 Inf 0.014 1.0000
## L_S low - M_M low 0.056645 9.25 Inf 0.006 1.0000
## L_S low - S low 0.030146 7.35 Inf 0.004 1.0000
## L_S low - S_L low 0.182261 10.58 Inf 0.017 1.0000
## L_S low - S_S low 0.026722 7.31 Inf 0.004 1.0000
## M low - M_M low -0.095833 9.14 Inf -0.010 1.0000
## M low - S low -0.122332 7.29 Inf -0.017 1.0000
## M low - S_L low 0.029783 10.65 Inf 0.003 1.0000
## M low - S_S low -0.125756 7.18 Inf -0.018 1.0000
## M_M low - S low -0.026499 7.53 Inf -0.004 1.0000
## M_M low - S_L low 0.125616 9.69 Inf 0.013 1.0000
## M_M low - S_S low -0.029923 6.67 Inf -0.004 1.0000
## S low - S_L low 0.152114 9.39 Inf 0.016 1.0000
## S low - S_S low -0.003424 9.21 Inf 0.000 1.0000
## S_L low - S_S low -0.155538 8.92 Inf -0.017 1.0000
##
## Results are given on the log (not the response) scale.
## P value adjustment: tukey method for comparing a family of 14.2931142241337 estimates
high_L = c(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
high_L_L = c(0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
high_L_S = c(0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
high_M = c(0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
high_M_M = c(0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
high_S = c(0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
high_S_L = c(0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0)
high_S_S = c(0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0)
low_L = c(rep(0,8), 1, rep(0,7))
low_L_L = c(rep(0,9), 1, rep(0,6))
low_L_S = c(rep(0,10), 1, rep(0,5))
low_M = c(rep(0,11), 1, rep(0,4))
low_M_M = c(rep(0,12), 1, rep(0,3))
low_S = c(rep(0,13), 1, rep(0,2))
low_S_L = c(rep(0,14), 1, rep(0,1))
low_S_S = c(rep(0,15), 1)
n_of_digits = 3
contrasts = contrast(emmeans_output,
method = list("high S_L - S" = high_S_L - high_S,
"high S_L - S_S" = high_S_L - high_S_S,
"high S_S - S" = high_S_S - high_S,
"high M_M - M" = high_M_M - high_M,
"high L_S - L" = high_L_S - high_L,
"high L_S - L_L" = high_L_S - high_L_L,
"high L_L - L" = high_L_L - high_L,
"low S_L - S" = low_S_L - low_S,
"low S_L - S_S" = low_S_L - low_S_S,
"low S_S - S" = low_S_S - low_S,
"low M_M - M" = low_M_M - low_M,
"low L_S - L" = low_L_S - low_L,
"low L_S - L_L" = low_L_S - low_L_L,
"low L_L - L" = low_L_L - low_L)) %>%
as.data.frame() %>%
mutate(p.value = round(p.value, digits = n_of_digits),
estimate = round(estimate, digits = n_of_digits),
SE = round(SE, digits = n_of_digits),
df = round(df, digits = n_of_digits),
z.ratio = round(z.ratio, digits = n_of_digits),
e = "",
e = ifelse(p.value > 0.1,
"",
e),
e = ifelse(p.value < 0.05,
"*",
e),
e = ifelse(p.value < 0.01,
"**",
e),
e = ifelse(p.value < 0.001,
"***",
e)) %>%
rename(" " = e)
# --- SHOW ECOSYSTEM TYPE CONSTRASTS --- #
contrasts
## contrast estimate SE df z.ratio p.value
## 1 high S_L - S 0.002 4.430 Inf 0.001 1.000
## 2 high S_L - S_S 0.005 9.331 Inf 0.001 1.000
## 3 high S_S - S -0.003 3.899 Inf -0.001 0.999
## 4 high M_M - M 0.045 9.425 Inf 0.005 0.996
## 5 high L_S - L 0.008 10.807 Inf 0.001 0.999
## 6 high L_S - L_L -0.063 9.298 Inf -0.007 0.995
## 7 high L_L - L 0.070 9.375 Inf 0.008 0.994
## 8 low S_L - S -0.152 9.389 Inf -0.016 0.987
## 9 low S_L - S_S -0.156 8.917 Inf -0.017 0.986
## 10 low S_S - S 0.003 9.214 Inf 0.000 1.000
## 11 low M_M - M 0.096 9.139 Inf 0.010 0.992
## 12 low L_S - L 0.146 10.257 Inf 0.014 0.989
## 13 low L_S - L_L 0.014 8.703 Inf 0.002 0.999
## 14 low L_L - L 0.132 9.413 Inf 0.014 0.989
# --- CONSTRUCT RESIDUALS VS FITTED VALUES PLOT --- #
res_vs_fit = data_for_analysis %>%
mutate(predicted = fitted(full_model),
residuals = resid(full_model)) %>%
plot_ly(x = ~predicted,
y = ~residuals,
type = "scatter",
mode = "markers",
marker = list(size = 5, color = "#4C78A8"),
text = paste(" ID: ",
data_for_analysis$culture_ID,
"<br>",
"Day: ",
data_for_analysis$day,
"<br>",
"Patch Type: ",
data_for_analysis$ecosystem_type,
"<br>",
"Biomass density: ",
round(data_for_analysis$bioarea_mm2_per_ml, digits = 2),
"<br>",
"Species richness: ",
data_for_analysis$species_richness,
"<br>"),
hoverinfo = "text") %>%
plotly::layout(title = "Residuals vs. Fitted Values",
xaxis = list(title = "Fitted Values"),
yaxis = list(title = "Residuals"))
# --- PLOT RESIDUALS --- #
qqnorm(resid(full_model))
qqline(resid(full_model))
res_vs_fit
response_variable_selected = "bioarea_mm2_per_ml"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT MEAN ± 95% CI --- #
"High disturbance"
## [1] "High disturbance"
plot.all.patches.points(data = ds_ecosystems_both_disturbances %>% filter(disturbance == "high"),
response_variable_selected)
"Low disturbance"
## [1] "Low disturbance"
plot.all.patches.points(data = ds_ecosystems_both_disturbances %>% filter(disturbance == "low"),
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. To do so, we go through the following steps.
# --- ADD BASELINES --- #
baselines = ds_ecosystems_both_disturbances %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
data_for_analysis = ds_ecosystems_both_disturbances %>%
left_join(baselines)
# --- FILTER DATA AND CHANGE THE NAME OF LEVELS --- #
data_for_analysis = data_for_analysis %>%
filter(time_point %in% time_points_model,
!is.na(!!sym(response_variable_selected)),
!is.na(water_addition_ml)) %>%
mutate(ecosystem_type = case_when(ecosystem_type == "Small unconnected" ~ "S",
ecosystem_type == "Medium unconnected" ~ "M",
ecosystem_type == "Large unconnected" ~ "L",
ecosystem_type == "Small connected to small" ~ "S_S",
ecosystem_type == "Small connected to large" ~ "S_L",
ecosystem_type == "Medium connected to medium" ~ "M_M",
ecosystem_type == "Large connected to large" ~ "L_L",
ecosystem_type == "Large connected to small" ~ "L_S",
TRUE ~ ecosystem_type))
# --- ADD EVAPORATION RATES RESIDUALS --- #
evaporation_model = lm(get(response_variable_selected) ~
ecosystem_type * disturbance * day +
baseline * day,
data = data_for_analysis)
par(mfrow = c(2, 2))
plot(evaporation_model)
data_for_analysis = data_for_analysis %>%
mutate(evaporation_residuals = residuals(evaporation_model))
# --- PLOT MEAN ± 95% CI OF FILTERED DATA --- #
"High disturbance"
## [1] "High disturbance"
plot.all.patches.points(data = data_for_analysis %>% filter(disturbance == "high"),
response_variable_selected)
"Low disturbance"
## [1] "Low disturbance"
plot.all.patches.points(data = data_for_analysis %>% filter(disturbance == "low"),
response_variable_selected)
# --- CHECK COLLINEARITY --- #
# # Select the relevant numeric columns (ensure that they are numeric)
# numeric_data <- data_for_analysis %>%
# select(day, water_addition_ml, baseline)
#
# # Calculate the correlation matrix
# cor_matrix <- cor(numeric_data, use = "complete.obs")
#
# # Use corrplot to visualize the correlation matrix
# corrplot::corrplot(cor_matrix, method = 'number')
# --- CONSTRUCT MODEL --- #
# full_model = lmer(get(response_variable_selected) ~
# ecosystem_type * disturbance * day +
# water_addition_ml * day +
# baseline * day +
# (day | culture_ID),
# data = data_for_analysis,
# REML = FALSE)
full_model <- glmmTMB(get(response_variable_selected) ~
ecosystem_type * disturbance * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = data_for_analysis,
family = tweedie(link = "log"),
control = glmmTMBControl(optimizer = "optim"))
## Warning in finalizeTMB(TMBStruc, obj, fit, h, data.tmb.old): Model convergence
## problem; non-positive-definite Hessian matrix. See vignette('troubleshooting')
## Warning in finalizeTMB(TMBStruc, obj, fit, h, data.tmb.old): Model convergence
## problem; . See vignette('troubleshooting'), help('diagnose')
# --- SHOW MODEL SUMMARY --- #
print(summary(full_model), digits = 1)
## Family: tweedie ( log )
## Formula:
## get(response_variable_selected) ~ ecosystem_type * disturbance *
## scale(day) + scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: data_for_analysis
##
## AIC BIC logLik deviance df.resid
## NA NA NA NA 502
##
## Random effects:
##
## Conditional model:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 1.0 1.0
## day 0.7 0.9 -0.05
## Number of obs: 543, groups: culture_ID, 109
##
## Dispersion parameter for tweedie family (): 0.792
##
## Conditional model:
## Estimate Std. Error z value
## (Intercept) 0.082 8.012 0.0
## ecosystem_typeL_L 0.041 9.546 0.0
## ecosystem_typeL_S 0.117 10.968 0.0
## ecosystem_typeM 0.045 11.176 0.0
## ecosystem_typeM_M 0.045 9.570 0.0
## ecosystem_typeS 0.222 18.632 0.0
## ecosystem_typeS_L 0.039 12.924 0.0
## ecosystem_typeS_S 0.033 13.141 0.0
## disturbancelow 0.122 11.559 0.0
## scale(day) -0.529 2.275 -0.2
## scale(water_addition_ml) 0.073 0.067 1.1
## scale(baseline) -0.014 1.822 0.0
## ecosystem_typeL_L:disturbancelow 0.048 13.517 0.0
## ecosystem_typeL_S:disturbancelow 0.062 15.452 0.0
## ecosystem_typeM:disturbancelow -0.026 15.808 0.0
## ecosystem_typeM_M:disturbancelow 0.034 13.507 0.0
## ecosystem_typeS:disturbancelow 0.021 16.115 0.0
## ecosystem_typeS_L:disturbancelow -0.062 15.339 0.0
## ecosystem_typeS_S:disturbancelow 0.042 13.497 0.0
## ecosystem_typeL_L:scale(day) 0.057 2.712 0.0
## ecosystem_typeL_S:scale(day) -0.006 3.116 0.0
## ecosystem_typeM:scale(day) 0.033 3.176 0.0
## ecosystem_typeM_M:scale(day) -0.022 2.719 0.0
## ecosystem_typeS:scale(day) 0.168 5.306 0.0
## ecosystem_typeS_L:scale(day) 0.185 3.674 0.1
## ecosystem_typeS_S:scale(day) 0.004 3.734 0.0
## disturbancelow:scale(day) -0.104 3.290 0.0
## scale(day):scale(water_addition_ml) -0.045 0.059 -0.8
## scale(day):scale(baseline) 0.025 0.518 0.0
## ecosystem_typeL_L:disturbancelow:scale(day) -0.128 3.841 0.0
## ecosystem_typeL_S:disturbancelow:scale(day) -0.053 4.391 0.0
## ecosystem_typeM:disturbancelow:scale(day) -0.062 4.493 0.0
## ecosystem_typeM_M:disturbancelow:scale(day) 0.008 3.839 0.0
## ecosystem_typeS:disturbancelow:scale(day) 0.041 4.592 0.0
## ecosystem_typeS_L:disturbancelow:scale(day) -0.042 4.361 0.0
## ecosystem_typeS_S:disturbancelow:scale(day) 0.029 3.839 0.0
## Pr(>|z|)
## (Intercept) 1.0
## ecosystem_typeL_L 1.0
## ecosystem_typeL_S 1.0
## ecosystem_typeM 1.0
## ecosystem_typeM_M 1.0
## ecosystem_typeS 1.0
## ecosystem_typeS_L 1.0
## ecosystem_typeS_S 1.0
## disturbancelow 1.0
## scale(day) 0.8
## scale(water_addition_ml) 0.3
## scale(baseline) 1.0
## ecosystem_typeL_L:disturbancelow 1.0
## ecosystem_typeL_S:disturbancelow 1.0
## ecosystem_typeM:disturbancelow 1.0
## ecosystem_typeM_M:disturbancelow 1.0
## ecosystem_typeS:disturbancelow 1.0
## ecosystem_typeS_L:disturbancelow 1.0
## ecosystem_typeS_S:disturbancelow 1.0
## ecosystem_typeL_L:scale(day) 1.0
## ecosystem_typeL_S:scale(day) 1.0
## ecosystem_typeM:scale(day) 1.0
## ecosystem_typeM_M:scale(day) 1.0
## ecosystem_typeS:scale(day) 1.0
## ecosystem_typeS_L:scale(day) 1.0
## ecosystem_typeS_S:scale(day) 1.0
## disturbancelow:scale(day) 1.0
## scale(day):scale(water_addition_ml) 0.4
## scale(day):scale(baseline) 1.0
## ecosystem_typeL_L:disturbancelow:scale(day) 1.0
## ecosystem_typeL_S:disturbancelow:scale(day) 1.0
## ecosystem_typeM:disturbancelow:scale(day) 1.0
## ecosystem_typeM_M:disturbancelow:scale(day) 1.0
## ecosystem_typeS:disturbancelow:scale(day) 1.0
## ecosystem_typeS_L:disturbancelow:scale(day) 1.0
## ecosystem_typeS_S:disturbancelow:scale(day) 1.0
# --- RUN ANOVA --- #
car::Anova(full_model, type = "III")
## Analysis of Deviance Table (Type III Wald chisquare tests)
##
## Response: get(response_variable_selected)
## Chisq Df Pr(>Chisq)
## (Intercept) 0.0001 1 0.9919
## ecosystem_type 0.0004 7 1.0000
## disturbance 0.0001 1 0.9916
## scale(day) 0.0541 1 0.8161
## scale(water_addition_ml) 1.2106 1 0.2712
## scale(baseline) 0.0001 1 0.9940
## ecosystem_type:disturbance 0.0001 7 1.0000
## ecosystem_type:scale(day) 0.0081 7 1.0000
## disturbance:scale(day) 0.0010 1 0.9747
## scale(day):scale(water_addition_ml) 0.5918 1 0.4417
## scale(day):scale(baseline) 0.0023 1 0.9617
## ecosystem_type:disturbance:scale(day) 0.0038 7 1.0000
# --- GET ECOSYSTEM TYPE CONSTRASTS --- #
emmeans_output = emmeans(full_model,
specs = pairwise ~ ecosystem_type * disturbance,
adjust = "tukey",
bias.adj = TRUE,
lmer.df = "satterthwaite")
emmeans_output
## $emmeans
## ecosystem_type disturbance emmean SE df asymp.LCL asymp.UCL
## L high 0.0816 8.01 Inf -15.6 15.8
## L_L high 0.1229 5.79 Inf -11.2 11.5
## L_S high 0.1982 7.78 Inf -15.0 15.4
## M high 0.1263 7.80 Inf -15.2 15.4
## M_M high 0.1270 5.49 Inf -10.6 10.9
## S high 0.3036 15.11 Inf -29.3 29.9
## S_L high 0.1210 9.07 Inf -17.7 17.9
## S_S high 0.1144 8.82 Inf -17.2 17.4
## L low 0.2038 9.87 Inf -19.1 19.6
## L_L low 0.2927 7.77 Inf -14.9 15.5
## L_S low 0.3821 8.80 Inf -16.9 17.6
## M low 0.2222 8.34 Inf -16.1 16.6
## M_M low 0.2836 6.23 Inf -11.9 12.5
## S low 0.4465 9.33 Inf -17.8 18.7
## S_L low 0.1811 7.76 Inf -15.0 15.4
## S_S low 0.2787 6.42 Inf -12.3 12.9
##
## Results are given on the log (not the response) scale.
## Confidence level used: 0.95
##
## $contrasts
## contrast estimate SE df z.ratio p.value
## L high - L_L high -0.041320 9.55 Inf -0.004 1.0000
## L high - L_S high -0.116634 10.97 Inf -0.011 1.0000
## L high - M high -0.044711 11.18 Inf -0.004 1.0000
## L high - M_M high -0.045352 9.57 Inf -0.005 1.0000
## L high - S high -0.221965 18.63 Inf -0.012 1.0000
## L high - S_L high -0.039397 12.92 Inf -0.003 1.0000
## L high - S_S high -0.032794 13.14 Inf -0.002 1.0000
## L high - L low -0.122230 11.56 Inf -0.011 1.0000
## L high - L_L low -0.211054 9.88 Inf -0.021 1.0000
## L high - L_S low -0.300509 10.99 Inf -0.027 1.0000
## L high - M low -0.140576 10.83 Inf -0.013 1.0000
## L high - M_M low -0.201956 9.43 Inf -0.021 1.0000
## L high - S low -0.364936 13.24 Inf -0.028 1.0000
## L high - S_L low -0.099516 11.17 Inf -0.009 1.0000
## L high - S_S low -0.197048 10.89 Inf -0.018 1.0000
## L_L high - L_S high -0.075314 9.56 Inf -0.008 1.0000
## L_L high - M high -0.003391 9.56 Inf 0.000 1.0000
## L_L high - M_M high -0.004032 7.89 Inf -0.001 1.0000
## L_L high - S high -0.180645 17.48 Inf -0.010 1.0000
## L_L high - S_L high 0.001924 11.54 Inf 0.000 1.0000
## L_L high - S_S high 0.008526 11.64 Inf 0.001 1.0000
## L_L high - L low -0.080910 10.33 Inf -0.008 1.0000
## L_L high - L_L low -0.169733 8.52 Inf -0.020 1.0000
## L_L high - L_S low -0.259189 9.73 Inf -0.027 1.0000
## L_L high - M low -0.099256 9.62 Inf -0.010 1.0000
## L_L high - M_M low -0.160636 7.92 Inf -0.020 1.0000
## L_L high - S low -0.323616 11.72 Inf -0.028 1.0000
## L_L high - S_L low -0.058196 9.58 Inf -0.006 1.0000
## L_L high - S_S low -0.155728 9.38 Inf -0.017 1.0000
## L_S high - M high 0.071923 11.03 Inf 0.007 1.0000
## L_S high - M_M high 0.071282 9.45 Inf 0.008 1.0000
## L_S high - S high -0.105330 17.64 Inf -0.006 1.0000
## L_S high - S_L high 0.077238 12.29 Inf 0.006 1.0000
## L_S high - S_S high 0.083840 12.29 Inf 0.007 1.0000
## L_S high - L low -0.005596 12.13 Inf 0.000 1.0000
## L_S high - L_L low -0.094419 10.51 Inf -0.009 1.0000
## L_S high - L_S low -0.183875 11.39 Inf -0.016 1.0000
## L_S high - M low -0.023942 11.11 Inf -0.002 1.0000
## L_S high - M_M low -0.085322 9.66 Inf -0.009 1.0000
## L_S high - S low -0.248302 12.56 Inf -0.020 1.0000
## L_S high - S_L low 0.017118 11.01 Inf 0.002 1.0000
## L_S high - S_S low -0.080414 10.33 Inf -0.008 1.0000
## M high - M_M high -0.000641 9.56 Inf 0.000 1.0000
## M high - S high -0.177254 17.20 Inf -0.010 1.0000
## M high - S_L high 0.005314 12.10 Inf 0.000 1.0000
## M high - S_S high 0.011917 11.92 Inf 0.001 1.0000
## M high - L low -0.077519 12.35 Inf -0.006 1.0000
## M high - L_L low -0.166343 10.84 Inf -0.015 1.0000
## M high - L_S low -0.255798 11.64 Inf -0.022 1.0000
## M high - M low -0.095865 11.42 Inf -0.008 1.0000
## M high - M_M low -0.157245 9.96 Inf -0.016 1.0000
## M high - S low -0.320225 12.19 Inf -0.026 1.0000
## M high - S_L low -0.054805 10.91 Inf -0.005 1.0000
## M high - S_S low -0.152337 10.30 Inf -0.015 1.0000
## M_M high - S high -0.176613 16.56 Inf -0.011 1.0000
## M_M high - S_L high 0.005955 10.88 Inf 0.001 1.0000
## M_M high - S_S high 0.012558 10.81 Inf 0.001 1.0000
## M_M high - L low -0.076878 10.94 Inf -0.007 1.0000
## M_M high - L_L low -0.165702 9.09 Inf -0.018 1.0000
## M_M high - L_S low -0.255157 10.06 Inf -0.025 1.0000
## M_M high - M low -0.095225 9.72 Inf -0.010 1.0000
## M_M high - M_M low -0.156604 8.04 Inf -0.019 1.0000
## M_M high - S low -0.319584 11.16 Inf -0.029 1.0000
## M_M high - S_L low -0.054164 9.53 Inf -0.006 1.0000
## M_M high - S_S low -0.151697 8.65 Inf -0.018 1.0000
## S high - S_L high 0.182568 13.87 Inf 0.013 1.0000
## S high - S_S high 0.189170 11.58 Inf 0.016 1.0000
## S high - L low 0.099735 21.90 Inf 0.005 1.0000
## S high - L_L low 0.010911 20.76 Inf 0.001 1.0000
## S high - L_S low -0.078544 20.35 Inf -0.004 1.0000
## S high - M low 0.081388 19.44 Inf 0.004 1.0000
## S high - M_M low 0.020009 18.46 Inf 0.001 1.0000
## S high - S low -0.142971 13.67 Inf -0.010 1.0000
## S high - S_L low 0.122449 17.07 Inf 0.007 1.0000
## S high - S_S low 0.024916 13.76 Inf 0.002 1.0000
## S_L high - S_S high 0.006602 9.71 Inf 0.001 1.0000
## S_L high - L low -0.082834 15.48 Inf -0.005 1.0000
## S_L high - L_L low -0.171657 14.06 Inf -0.012 1.0000
## S_L high - L_S low -0.261113 14.20 Inf -0.018 1.0000
## S_L high - M low -0.101180 13.50 Inf -0.007 1.0000
## S_L high - M_M low -0.162560 12.21 Inf -0.013 1.0000
## S_L high - S low -0.325540 10.99 Inf -0.030 1.0000
## S_L high - S_L low -0.060120 12.01 Inf -0.005 1.0000
## S_L high - S_S low -0.157652 9.60 Inf -0.016 1.0000
## S_S high - L low -0.089436 16.16 Inf -0.006 1.0000
## S_S high - L_L low -0.178259 14.76 Inf -0.012 1.0000
## S_S high - L_S low -0.267715 14.69 Inf -0.018 1.0000
## S_S high - M low -0.107782 13.88 Inf -0.008 1.0000
## S_S high - M_M low -0.169162 12.57 Inf -0.013 1.0000
## S_S high - S low -0.332142 9.64 Inf -0.034 1.0000
## S_S high - S_L low -0.066722 11.81 Inf -0.006 1.0000
## S_S high - S_S low -0.164254 8.64 Inf -0.019 1.0000
## L low - L_L low -0.088824 9.48 Inf -0.009 1.0000
## L low - L_S low -0.178279 11.09 Inf -0.016 1.0000
## L low - M low -0.018346 11.44 Inf -0.002 1.0000
## L low - M_M low -0.079726 10.06 Inf -0.008 1.0000
## L low - S low -0.242706 15.71 Inf -0.015 1.0000
## L low - S_L low 0.022714 12.44 Inf 0.002 1.0000
## L low - S_S low -0.074818 13.45 Inf -0.006 1.0000
## L_L low - L_S low -0.089455 9.54 Inf -0.009 1.0000
## L_L low - M low 0.070477 9.82 Inf 0.007 1.0000
## L_L low - M_M low 0.009098 8.14 Inf 0.001 1.0000
## L_L low - S low -0.153882 14.35 Inf -0.011 1.0000
## L_L low - S_L low 0.111538 10.91 Inf 0.010 1.0000
## L_L low - S_S low 0.014005 11.81 Inf 0.001 1.0000
## L_S low - M low 0.159933 11.00 Inf 0.015 1.0000
## L_S low - M_M low 0.098553 9.53 Inf 0.010 1.0000
## L_S low - S low -0.064427 14.47 Inf -0.004 1.0000
## L_S low - S_L low 0.200993 11.69 Inf 0.017 1.0000
## L_S low - S_S low 0.103460 12.13 Inf 0.009 1.0000
## M low - M_M low -0.061380 9.42 Inf -0.007 1.0000
## M low - S low -0.224360 13.83 Inf -0.016 1.0000
## M low - S_L low 0.041060 11.43 Inf 0.004 1.0000
## M low - S_S low -0.056472 11.41 Inf -0.005 1.0000
## M_M low - S low -0.162980 12.56 Inf -0.013 1.0000
## M_M low - S_L low 0.102440 9.97 Inf 0.010 1.0000
## M_M low - S_S low 0.004908 9.91 Inf 0.000 1.0000
## S low - S_L low 0.265420 12.12 Inf 0.022 1.0000
## S low - S_S low 0.167887 9.84 Inf 0.017 1.0000
## S_L low - S_S low -0.097532 10.20 Inf -0.010 1.0000
##
## Results are given on the log (not the response) scale.
## P value adjustment: tukey method for comparing a family of 16 estimates
high_L = c(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
high_L_L = c(0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
high_L_S = c(0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
high_M = c(0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
high_M_M = c(0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
high_S = c(0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
high_S_L = c(0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0)
high_S_S = c(0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0)
low_L = c(rep(0,8), 1, rep(0,7))
low_L_L = c(rep(0,9), 1, rep(0,6))
low_L_S = c(rep(0,10), 1, rep(0,5))
low_M = c(rep(0,11), 1, rep(0,4))
low_M_M = c(rep(0,12), 1, rep(0,3))
low_S = c(rep(0,13), 1, rep(0,2))
low_S_L = c(rep(0,14), 1, rep(0,1))
low_S_S = c(rep(0,15), 1)
n_of_digits = 3
contrasts = contrast(emmeans_output,
method = list("high S_L - S" = high_S_L - high_S,
"high S_L - S_S" = high_S_L - high_S_S,
"high S_S - S" = high_S_S - high_S,
"high M_M - M" = high_M_M - high_M,
"high L_S - L" = high_L_S - high_L,
"high L_S - L_L" = high_L_S - high_L_L,
"high L_L - L" = high_L_L - high_L,
"low S_L - S" = low_S_L - low_S,
"low S_L - S_S" = low_S_L - low_S_S,
"low S_S - S" = low_S_S - low_S,
"low M_M - M" = low_M_M - low_M,
"low L_S - L" = low_L_S - low_L,
"low L_S - L_L" = low_L_S - low_L_L,
"low L_L - L" = low_L_L - low_L)) %>%
as.data.frame() %>%
mutate(p.value = round(p.value, digits = n_of_digits),
estimate = round(estimate, digits = n_of_digits),
SE = round(SE, digits = n_of_digits),
df = round(df, digits = n_of_digits),
z.ratio = round(z.ratio, digits = n_of_digits),
e = "",
e = ifelse(p.value > 0.1,
"",
e),
e = ifelse(p.value < 0.05,
"*",
e),
e = ifelse(p.value < 0.01,
"**",
e),
e = ifelse(p.value < 0.001,
"***",
e)) %>%
rename(" " = e)
# --- SHOW ECOSYSTEM TYPE CONSTRASTS --- #
contrasts
## contrast estimate SE df z.ratio p.value
## 1 high S_L - S -0.183 13.873 Inf -0.013 0.989
## 2 high S_L - S_S 0.007 9.706 Inf 0.001 0.999
## 3 high S_S - S -0.189 11.584 Inf -0.016 0.987
## 4 high M_M - M 0.001 9.562 Inf 0.000 1.000
## 5 high L_S - L 0.117 10.968 Inf 0.011 0.992
## 6 high L_S - L_L 0.075 9.564 Inf 0.008 0.994
## 7 high L_L - L 0.041 9.546 Inf 0.004 0.997
## 8 low S_L - S -0.265 12.123 Inf -0.022 0.983
## 9 low S_L - S_S -0.098 10.204 Inf -0.010 0.992
## 10 low S_S - S -0.168 9.839 Inf -0.017 0.986
## 11 low M_M - M 0.061 9.423 Inf 0.007 0.995
## 12 low L_S - L 0.178 11.095 Inf 0.016 0.987
## 13 low L_S - L_L 0.089 9.538 Inf 0.009 0.993
## 14 low L_L - L 0.089 9.479 Inf 0.009 0.993
# --- CONSTRUCT RESIDUALS VS FITTED VALUES PLOT --- #
res_vs_fit = data_for_analysis %>%
mutate(predicted = fitted(full_model),
residuals = resid(full_model)) %>%
plot_ly(x = ~predicted,
y = ~residuals,
type = "scatter",
mode = "markers",
marker = list(size = 5, color = "#4C78A8"),
text = paste(" ID: ",
data_for_analysis$culture_ID,
"<br>",
"Day: ",
data_for_analysis$day,
"<br>",
"Patch Type: ",
data_for_analysis$ecosystem_type,
"<br>",
"Biomass density: ",
round(data_for_analysis$bioarea_mm2_per_ml, digits = 2),
"<br>",
"Species richness: ",
data_for_analysis$species_richness,
"<br>"),
hoverinfo = "text") %>%
plotly::layout(title = "Residuals vs. Fitted Values",
xaxis = list(title = "Fitted Values"),
yaxis = list(title = "Residuals"))
# --- PLOT RESIDUALS --- #
qqnorm(resid(full_model))
qqline(resid(full_model))
res_vs_fit
ecosystem_type_selected = c("Small unconnected",
"Medium unconnected",
"Large unconnected")
response_variable_selected = "shannon"
We want to know whether the size of ecosystems influenced this response variable. We only look at unconnected ecosystems so that the effects of connection don’t confound the effects of ecosystem size. We first start from plotting how this response variable changed in different sizes throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
## Warning in qt(conf.interval/2 + 0.5, datac$N - 1): NaNs produced
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(metaecosystem == "no",
time_point %in% time_points_model,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- CALCULATE BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines,
!is.na(!!sym(response_variable_selected))) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how ecosystem size influenced this variable. To study the
effects of ecosystem size we compare two models to a null model using
ANOVA: a full model and a reduced model. In all models, we treat culture
ID as having a random effect on how the slope and intercept of the
relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of size with time
(Response variable ~ size * day + (day | culture ID)), the
reduced model contains the size but without the interaction with time
(Response variable ~ size + day + (day | culture ID)), and
the null model doesn’t contain the size at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem size had an
effect.
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_size * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE)
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_size +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE)
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE)
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -34.1 < 0.001 **** very strong
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_size * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
##
## AIC BIC logLik deviance df.resid
## 40.6 70.6 -6.3 12.6 49
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.39 -0.62 0.06 0.74 2.18
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 8e-10 3e-05
## day 1e-12 1e-06 -1.00
## Residual 7e-02 3e-01
## Number of obs: 63, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 1.52 0.06 63.00 24.3 <2e-16
## ecosystem_sizeMedium -0.13 0.08 63.00 -1.6 0.116
## ecosystem_sizeSmall -1.28 0.11 63.00 -12.0 <2e-16
## scale(day) 0.05 0.06 63.00 0.8 0.404
## scale(water_addition_ml) 0.12 0.06 63.00 2.1 0.037
## scale(baseline) 0.03 0.04 63.00 0.8 0.447
## ecosystem_sizeMedium:scale(day) -0.09 0.08 63.00 -1.1 0.264
## ecosystem_sizeSmall:scale(day) -0.33 0.13 63.00 -2.5 0.015
## scale(day):scale(water_addition_ml) 0.19 0.06 63.00 3.4 0.001
## scale(day):scale(baseline) 0.05 0.04 63.00 1.2 0.231
##
## (Intercept) ***
## ecosystem_sizeMedium
## ecosystem_sizeSmall ***
## scale(day)
## scale(water_addition_ml) *
## scale(baseline)
## ecosystem_sizeMedium:scale(day)
## ecosystem_sizeSmall:scale(day) *
## scale(day):scale(water_addition_ml) **
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecsy_M ecsy_S scl(d) sc(__) scl(b) e_M:() e_S:() s():(_
## ecsystm_szM -0.659
## ecsystm_szS -0.554 0.458
## scale(day) 0.016 0.053 -0.003
## scl(wtr_d_) 0.340 -0.015 -0.177 0.285
## scale(bsln) -0.277 0.326 0.371 -0.006 -0.058
## ecsyst_M:() 0.023 -0.088 -0.053 -0.705 -0.018 -0.025
## ecsyst_S:() -0.044 -0.063 0.068 -0.410 0.125 -0.111 0.414
## scl(d):(__) 0.401 0.030 0.030 0.128 0.535 0.068 -0.094 -0.358
## scl(dy):s() 0.020 -0.019 -0.063 -0.280 0.084 -0.059 0.328 0.357 -0.027
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -32.6 < 0.001 **** very strong
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_size + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
##
## AIC BIC logLik deviance df.resid
## 42.1 67.8 -9.0 18.1 51
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.27 -0.65 0.01 0.67 2.21
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 6e-02 0.24
## day 1e-04 0.01 -1.00
## Residual 7e-02 0.27
## Number of obs: 63, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 1.51 0.06 47.64 23.4 <2e-16
## ecosystem_sizeMedium -0.14 0.08 41.30 -1.8 0.09
## ecosystem_sizeSmall -1.28 0.11 45.63 -11.7 2e-15
## scale(day) -0.02 0.05 13.96 -0.4 0.69
## scale(water_addition_ml) 0.13 0.06 51.35 2.2 0.03
## scale(baseline) 0.02 0.04 43.64 0.5 0.64
## scale(day):scale(water_addition_ml) 0.13 0.05 58.76 2.4 0.02
## scale(day):scale(baseline) 0.08 0.04 9.48 2.1 0.07
##
## (Intercept) ***
## ecosystem_sizeMedium .
## ecosystem_sizeSmall ***
## scale(day)
## scale(water_addition_ml) *
## scale(baseline)
## scale(day):scale(water_addition_ml) *
## scale(day):scale(baseline) .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecsy_M ecsy_S scl(d) sc(__) scl(b) s():(_
## ecsystm_szM -0.659
## ecsystm_szS -0.548 0.456
## scale(day) -0.008 -0.018 -0.015
## scl(wtr_d_) 0.355 -0.014 -0.186 0.390
## scale(bsln) -0.282 0.323 0.381 -0.053 -0.043
## scl(d):(__) 0.424 0.010 0.051 0.000 0.628 0.025
## scl(dy):s() 0.029 0.018 -0.077 -0.025 0.050 -0.077 0.105
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "bioarea_mm2_per_ml"
We want to know whether the size of ecosystems influenced this response variable. We only look at unconnected ecosystems so that the effects of connection don’t confound the effects of ecosystem size. We first start from plotting how this response variable changed in different sizes throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(metaecosystem == "no",
time_point %in% time_points_model,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- CALCULATE BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines,
!is.na(!!sym(response_variable_selected))) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how ecosystem size influenced this variable. To study the
effects of ecosystem size we compare two models to a null model using
ANOVA: a full model and a reduced model. In all models, we treat culture
ID as having a random effect on how the slope and intercept of the
relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of size with time
(Response variable ~ size * day + (day | culture ID)), the
reduced model contains the size but without the interaction with time
(Response variable ~ size + day + (day | culture ID)), and
the null model doesn’t contain the size at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem size had an
effect.
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_size * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE)
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_size +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE)
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE)
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -30.1 < 0.001 **** very strong
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_size * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
##
## AIC BIC logLik deviance df.resid
## 143.1 174.4 -57.6 115.1 55
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.10 -0.60 -0.05 0.37 2.84
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 8e-02 0.287
## day 3e-05 0.006 -1.00
## Residual 3e-01 0.533
## Number of obs: 69, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 2.913 0.162 16.384 18.0 3e-12
## ecosystem_sizeMedium -1.324 0.228 14.168 -5.8 4e-05
## ecosystem_sizeSmall -2.817 0.242 15.119 -11.6 6e-09
## scale(day) -1.404 0.130 52.775 -10.8 6e-15
## scale(water_addition_ml) 0.080 0.103 59.854 0.8 0.4
## scale(baseline) -0.009 0.102 14.599 -0.1 0.9
## ecosystem_sizeMedium:scale(day) 0.801 0.185 51.625 4.3 7e-05
## ecosystem_sizeSmall:scale(day) 1.448 0.207 53.405 7.0 4e-09
## scale(day):scale(water_addition_ml) -0.014 0.107 58.073 -0.1 0.9
## scale(day):scale(baseline) 0.319 0.085 52.788 3.7 5e-04
##
## (Intercept) ***
## ecosystem_sizeMedium ***
## ecosystem_sizeSmall ***
## scale(day) ***
## scale(water_addition_ml)
## scale(baseline)
## ecosystem_sizeMedium:scale(day) ***
## ecosystem_sizeSmall:scale(day) ***
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline) ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecsy_M ecsy_S scl(d) sc(__) scl(b) e_M:() e_S:() s():(_
## ecsystm_szM -0.743
## ecsystm_szS -0.710 0.607
## scale(day) -0.078 0.077 0.027
## scl(wtr_d_) 0.203 0.066 -0.130 0.184
## scale(bsln) -0.469 0.566 0.507 0.056 0.115
## ecsyst_M:() 0.085 -0.085 -0.060 -0.771 0.033 -0.038
## ecsyst_S:() -0.003 -0.067 -0.123 -0.617 -0.022 -0.068 0.549
## scl(d):(__) 0.274 0.047 0.039 -0.033 0.569 0.082 0.071 -0.300
## scl(dy):s() 0.102 -0.031 -0.047 -0.504 0.126 -0.055 0.566 0.387 0.242
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -6.8 0.004 *** strong
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_size + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
##
## AIC BIC logLik deviance df.resid
## 166.4 193.2 -71.2 142.4 57
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.03 -0.62 -0.06 0.54 2.53
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 2.872 1.69
## day 0.005 0.07 -1.00
## Residual 0.342 0.58
## Number of obs: 69, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 2.64 0.18 12.38 15.0 3e-09
## ecosystem_sizeMedium -0.94 0.23 20.14 -4.1 5e-04
## ecosystem_sizeSmall -2.15 0.24 20.84 -8.9 1e-08
## scale(day) -0.75 0.14 17.09 -5.4 5e-05
## scale(water_addition_ml) 0.10 0.11 45.26 0.8 0.4
## scale(baseline) 0.14 0.12 5.88 1.2 0.3
## scale(day):scale(water_addition_ml) 0.09 0.12 44.58 0.8 0.4
## scale(day):scale(baseline) 0.03 0.13 14.71 0.2 0.8
##
## (Intercept) ***
## ecosystem_sizeMedium ***
## ecosystem_sizeSmall ***
## scale(day) ***
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecsy_M ecsy_S scl(d) sc(__) scl(b) s():(_
## ecsystm_szM -0.671
## ecsystm_szS -0.679 0.588
## scale(day) -0.347 -0.001 -0.022
## scl(wtr_d_) 0.205 0.087 -0.155 0.196
## scale(bsln) -0.372 0.490 0.422 0.012 0.111
## scl(d):(__) 0.322 0.074 -0.079 -0.129 0.572 0.045
## scl(dy):s() 0.056 0.025 -0.026 -0.037 0.087 -0.478 0.212
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "species_richness"
We want to know whether the size of ecosystems influenced this response variable. We only look at unconnected ecosystems so that the effects of connection don’t confound the effects of ecosystem size. We first start from plotting how this response variable changed in different sizes throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(metaecosystem == "no",
time_point %in% time_points_model,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- CALCULATE BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines,
!is.na(!!sym(response_variable_selected))) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how ecosystem size influenced this variable. To study the
effects of ecosystem size we compare two models to a null model using
ANOVA: a full model and a reduced model. In all models, we treat culture
ID as having a random effect on how the slope and intercept of the
relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of size with time
(Response variable ~ size * day + (day | culture ID)), the
reduced model contains the size but without the interaction with time
(Response variable ~ size + day + (day | culture ID)), and
the null model doesn’t contain the size at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem size had an
effect.
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_size * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE)
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_size +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE)
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE)
## Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, :
## Model failed to converge with max|grad| = 0.00248252 (tol = 0.002, component 1)
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -43.1 < 0.001 **** very strong
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_size * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
##
## AIC BIC logLik deviance df.resid
## 241.7 273.0 -106.8 213.7 55
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.96 -0.63 0.04 0.59 2.07
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 1.118 1.06
## day 0.002 0.05 -1.00
## Residual 1.222 1.11
## Number of obs: 69, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 6.9 0.3 54.0 27.2 <2e-16
## ecosystem_sizeMedium -1.3 0.3 45.7 -4.1 1e-04
## ecosystem_sizeSmall -5.9 0.4 49.2 -16.0 <2e-16
## scale(day) -0.1 0.3 16.5 -0.4 0.7
## scale(water_addition_ml) 0.3 0.2 61.9 1.3 0.2
## scale(baseline) 0.1 0.1 47.4 0.9 0.4
## ecosystem_sizeMedium:scale(day) -0.5 0.4 14.6 -1.5 0.2
## ecosystem_sizeSmall:scale(day) -0.5 0.4 22.5 -1.1 0.3
## scale(day):scale(water_addition_ml) 0.3 0.2 64.9 1.3 0.2
## scale(day):scale(baseline) 0.2 0.2 16.1 1.5 0.1
##
## (Intercept) ***
## ecosystem_sizeMedium ***
## ecosystem_sizeSmall ***
## scale(day)
## scale(water_addition_ml)
## scale(baseline)
## ecosystem_sizeMedium:scale(day)
## ecosystem_sizeSmall:scale(day)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecsy_M ecsy_S scl(d) sc(__) scl(b) e_M:() e_S:() s():(_
## ecsystm_szM -0.645
## ecsystm_szS -0.608 0.460
## scale(day) -0.001 0.066 -0.010
## scl(wtr_d_) 0.363 -0.021 -0.271 0.269
## scale(bsln) -0.183 0.169 0.224 -0.024 -0.128
## ecsyst_M:() 0.021 -0.104 -0.054 -0.698 -0.061 -0.009
## ecsyst_S:() -0.094 -0.052 -0.129 -0.573 -0.095 -0.054 0.465
## scl(d):(__) 0.421 -0.004 0.009 0.128 0.571 -0.034 -0.109 -0.429
## scl(dy):s() -0.072 -0.011 -0.050 -0.184 -0.109 -0.066 0.186 0.238 -0.199
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -44.9 < 0.001 **** very strong
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_size + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
##
## AIC BIC logLik deviance df.resid
## 239.9 266.7 -107.9 215.9 57
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -3.0 -0.6 0.1 0.6 2.1
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 1.687 1.30
## day 0.004 0.06 -1.00
## Residual 1.233 1.11
## Number of obs: 69, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 6.9 0.3 52.3 27.1 <2e-16
## ecosystem_sizeMedium -1.4 0.3 50.3 -4.3 7e-05
## ecosystem_sizeSmall -6.0 0.4 52.9 -16.2 <2e-16
## scale(day) -0.4 0.2 21.9 -2.2 0.04
## scale(water_addition_ml) 0.3 0.2 60.9 1.2 0.24
## scale(baseline) 0.1 0.1 46.5 0.9 0.40
## scale(day):scale(water_addition_ml) 0.2 0.2 60.8 1.0 0.34
## scale(day):scale(baseline) 0.3 0.2 15.7 1.8 0.08
##
## (Intercept) ***
## ecosystem_sizeMedium ***
## ecosystem_sizeSmall ***
## scale(day) *
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline) .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecsy_M ecsy_S scl(d) sc(__) scl(b) s():(_
## ecsystm_szM -0.649
## ecsystm_szS -0.629 0.460
## scale(day) -0.043 -0.011 -0.117
## scl(wtr_d_) 0.364 -0.029 -0.287 0.297
## scale(bsln) -0.191 0.169 0.218 -0.068 -0.135
## scl(d):(__) 0.427 -0.020 -0.056 -0.117 0.595 -0.067
## scl(dy):s() -0.057 0.009 -0.020 -0.007 -0.085 -0.076 -0.117
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "evenness_pielou"
We want to know whether the size of ecosystems influenced this response variable. We only look at unconnected ecosystems so that the effects of connection don’t confound the effects of ecosystem size. We first start from plotting how this response variable changed in different sizes throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
## Warning in qt(conf.interval/2 + 0.5, datac$N - 1): NaNs produced
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(metaecosystem == "no",
time_point %in% time_points_model,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- CALCULATE BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines,
!is.na(!!sym(response_variable_selected))) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
## Warning in qt(conf.interval/2 + 0.5, datac$N - 1): NaNs produced
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how ecosystem size influenced this variable. To study the
effects of ecosystem size we compare two models to a null model using
ANOVA: a full model and a reduced model. In all models, we treat culture
ID as having a random effect on how the slope and intercept of the
relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of size with time
(Response variable ~ size * day + (day | culture ID)), the
reduced model contains the size but without the interaction with time
(Response variable ~ size + day + (day | culture ID)), and
the null model doesn’t contain the size at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem size had an
effect.
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_size * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE)
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_size +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE)
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE)
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -35.2 < 0.001 **** very strong
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_size * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
##
## AIC BIC logLik deviance df.resid
## -44.4 -15.1 36.2 -72.4 46
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -3.4 -0.3 0.2 0.5 2.2
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 5e-02 0.218
## day 9e-05 0.009 -1.00
## Residual 1e-02 0.122
## Number of obs: 60, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 8e-01 3e-02 1e+01 25.1 7e-13
## ecosystem_sizeMedium 4e-02 4e-02 1e+01 1.0 0.35
## ecosystem_sizeSmall -5e-01 6e-02 2e+01 -7.8 1e-07
## scale(day) 4e-02 4e-02 6e+00 1.0 0.36
## scale(water_addition_ml) 4e-02 2e-02 3e+01 1.6 0.11
## scale(baseline) -5e-03 2e-02 1e+01 -0.2 0.81
## ecosystem_sizeMedium:scale(day) -1e-05 5e-02 5e+00 0.0 1.00
## ecosystem_sizeSmall:scale(day) -4e-01 7e-02 9e+00 -5.5 4e-04
## scale(day):scale(water_addition_ml) 4e-02 3e-02 4e+01 1.8 0.09
## scale(day):scale(baseline) -4e-04 2e-02 6e+00 0.0 0.99
##
## (Intercept) ***
## ecosystem_sizeMedium
## ecosystem_sizeSmall ***
## scale(day)
## scale(water_addition_ml)
## scale(baseline)
## ecosystem_sizeMedium:scale(day)
## ecosystem_sizeSmall:scale(day) ***
## scale(day):scale(water_addition_ml) .
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecsy_M ecsy_S scl(d) sc(__) scl(b) e_M:() e_S:() s():(_
## ecsystm_szM -0.673
## ecsystm_szS -0.553 0.430
## scale(day) -0.279 0.231 0.107
## scl(wtr_d_) 0.273 -0.008 -0.310 0.171
## scale(bsln) -0.258 0.291 0.392 0.081 -0.027
## ecsyst_M:() 0.209 -0.328 -0.147 -0.711 -0.001 -0.099
## ecsyst_S:() 0.113 -0.163 -0.285 -0.589 -0.023 -0.160 0.490
## scl(d):(__) 0.360 0.018 0.012 -0.018 0.461 0.063 -0.043 -0.250
## scl(dy):s() 0.128 -0.095 -0.146 -0.274 0.102 -0.326 0.285 0.406 0.082
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -22.6 < 0.001 **** very strong
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_size + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
##
## AIC BIC logLik deviance df.resid
## -31.8 -6.6 27.9 -55.8 48
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.9 -0.3 0.1 0.6 1.9
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 4e-01 0.64
## day 8e-04 0.03 -1.00
## Residual 1e-02 0.11
## Number of obs: 60, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.83 0.04 10.33 22 6e-10
## ecosystem_sizeMedium 0.04 0.04 30.33 1 0.32
## ecosystem_sizeSmall -0.67 0.06 37.44 -12 4e-14
## scale(day) -0.05 0.05 14.53 -1 0.34
## scale(water_addition_ml) 0.04 0.02 42.08 2 0.06
## scale(baseline) -0.04 0.03 4.72 -1 0.25
## scale(day):scale(water_addition_ml) 0.04 0.03 39.22 2 0.11
## scale(day):scale(baseline) 0.06 0.05 13.20 1 0.20
##
## (Intercept) ***
## ecosystem_sizeMedium
## ecosystem_sizeSmall ***
## scale(day)
## scale(water_addition_ml) .
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecsy_M ecsy_S scl(d) sc(__) scl(b) s():(_
## ecsystm_szM -0.527
## ecsystm_szS -0.465 0.421
## scale(day) -0.614 0.000 -0.028
## scl(wtr_d_) 0.221 -0.010 -0.325 0.119
## scale(bsln) -0.092 0.179 0.242 -0.072 -0.023
## scl(d):(__) 0.352 -0.010 -0.123 -0.118 0.460 -0.010
## scl(dy):s() -0.017 -0.001 -0.027 0.078 0.058 -0.784 0.104
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "median_body_area_µm2"
We want to know whether the size of ecosystems influenced this response variable. We only look at unconnected ecosystems so that the effects of connection don’t confound the effects of ecosystem size. We first start from plotting how this response variable changed in different sizes throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
## Warning in qt(conf.interval/2 + 0.5, datac$N - 1): NaNs produced
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(metaecosystem == "no",
time_point %in% time_points_model,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- CALCULATE BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines,
!is.na(!!sym(response_variable_selected))) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how ecosystem size influenced this variable. To study the
effects of ecosystem size we compare two models to a null model using
ANOVA: a full model and a reduced model. In all models, we treat culture
ID as having a random effect on how the slope and intercept of the
relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of size with time
(Response variable ~ size * day + (day | culture ID)), the
reduced model contains the size but without the interaction with time
(Response variable ~ size + day + (day | culture ID)), and
the null model doesn’t contain the size at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem size had an
effect.
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_size * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE)
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_size +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE)
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE)
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -4.3 0.015 ** moderate
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_size * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
##
## AIC BIC logLik deviance df.resid
## 1042.6 1072.6 -507.3 1014.6 49
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.97 -0.45 -0.02 0.68 2.22
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 3e+06 1719
## day 6e+03 77 -1.00
## Residual 4e+05 666
## Number of obs: 63, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 3190 187 20 17.1 3e-13
## ecosystem_sizeMedium 553 231 14 2.4 0.03
## ecosystem_sizeSmall 680 388 26 1.8 0.09
## scale(day) -312 250 11 -1.2 0.24
## scale(water_addition_ml) -166 143 49 -1.2 0.25
## scale(baseline) 226 149 21 1.5 0.14
## ecosystem_sizeMedium:scale(day) 227 331 10 0.7 0.51
## ecosystem_sizeSmall:scale(day) 911 553 19 1.6 0.12
## scale(day):scale(water_addition_ml) 8 152 53 0.1 0.96
## scale(day):scale(baseline) 102 209 13 0.5 0.63
##
## (Intercept) ***
## ecosystem_sizeMedium *
## ecosystem_sizeSmall .
## scale(day)
## scale(water_addition_ml)
## scale(baseline)
## ecosystem_sizeMedium:scale(day)
## ecosystem_sizeSmall:scale(day)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecsy_M ecsy_S scl(d) sc(__) scl(b) e_M:() e_S:() s():(_
## ecsystm_szM -0.612
## ecsystm_szS -0.566 0.287
## scale(day) -0.397 0.341 0.237
## scl(wtr_d_) 0.288 0.004 -0.104 0.196
## scale(bsln) -0.277 -0.016 0.678 0.099 0.003
## ecsyst_M:() 0.299 -0.518 -0.153 -0.660 -0.029 0.004
## ecsyst_S:() 0.149 -0.154 -0.242 -0.570 0.018 -0.176 0.304
## scl(d):(__) 0.374 0.007 0.030 0.100 0.538 0.025 -0.054 -0.298
## scl(dy):s() 0.057 0.005 -0.186 -0.304 -0.044 -0.332 -0.011 0.637 -0.103
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -5.8 0.007 *** strong
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_size + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
##
## AIC BIC logLik deviance df.resid
## 1041.1 1066.8 -508.6 1017.1 51
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.84 -0.48 0.06 0.67 2.01
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 4e+06 1974
## day 8e+03 89 -1.00
## Residual 4e+05 664
## Number of obs: 63, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 3132 180 28 17.4 <2e-16
## ecosystem_sizeMedium 636 197 34 3.2 0.003
## ecosystem_sizeSmall 883 378 35 2.3 0.025
## scale(day) -45 175 15 -0.3 0.801
## scale(water_addition_ml) -159 143 49 -1.1 0.272
## scale(baseline) 279 149 23 1.9 0.074
## scale(day):scale(water_addition_ml) 88 146 55 0.6 0.551
## scale(day):scale(baseline) -112 168 14 -0.7 0.516
##
## (Intercept) ***
## ecosystem_sizeMedium **
## ecosystem_sizeSmall *
## scale(day)
## scale(water_addition_ml)
## scale(baseline) .
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecsy_M ecsy_S scl(d) sc(__) scl(b) s():(_
## ecsystm_szM -0.553
## ecsystm_szS -0.548 0.250
## scale(day) -0.327 0.002 0.094
## scl(wtr_d_) 0.306 -0.014 -0.104 0.269
## scale(bsln) -0.281 -0.016 0.667 0.045 0.010
## scl(d):(__) 0.453 -0.025 -0.054 -0.086 0.567 -0.039
## scl(dy):s() 0.026 -0.005 -0.070 -0.083 -0.077 -0.331 0.131
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "auto_hetero_ratio"
We want to know whether the size of ecosystems influenced this response variable. We only look at unconnected ecosystems so that the effects of connection don’t confound the effects of ecosystem size. We first start from plotting how this response variable changed in different sizes throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
## Warning in qt(conf.interval/2 + 0.5, datac$N - 1): NaNs produced
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(metaecosystem == "no",
time_point %in% time_points_model,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- CALCULATE BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines,
!is.na(!!sym(response_variable_selected))) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how ecosystem size influenced this variable. To study the
effects of ecosystem size we compare two models to a null model using
ANOVA: a full model and a reduced model. In all models, we treat culture
ID as having a random effect on how the slope and intercept of the
relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of size with time
(Response variable ~ size * day + (day | culture ID)), the
reduced model contains the size but without the interaction with time
(Response variable ~ size + day + (day | culture ID)), and
the null model doesn’t contain the size at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem size had an
effect.
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_size * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE)
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_size +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE)
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE)
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -6.9 0.005 *** strong
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_size * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
##
## AIC BIC logLik deviance df.resid
## 6.1 36.1 11.0 -21.9 49
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.8 -0.3 0.0 0.2 5.6
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 5e-02 0.22
## day 2e-04 0.01 -1.00
## Residual 4e-02 0.19
## Number of obs: 63, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.32 0.05 37.19 6.5 1e-07
## ecosystem_sizeMedium -0.23 0.07 32.03 -3.4 0.002
## ecosystem_sizeSmall -0.32 0.08 38.83 -3.8 5e-04
## scale(day) 0.27 0.06 15.57 4.7 2e-04
## scale(water_addition_ml) 0.05 0.04 56.86 1.3 0.214
## scale(baseline) -0.05 0.03 32.87 -1.6 0.130
## ecosystem_sizeMedium:scale(day) -0.28 0.08 14.90 -3.4 0.004
## ecosystem_sizeSmall:scale(day) -0.30 0.11 30.78 -2.8 0.010
## scale(day):scale(water_addition_ml) 0.03 0.04 60.90 0.7 0.480
## scale(day):scale(baseline) -0.09 0.04 17.40 -2.2 0.045
##
## (Intercept) ***
## ecosystem_sizeMedium **
## ecosystem_sizeSmall ***
## scale(day) ***
## scale(water_addition_ml)
## scale(baseline)
## ecosystem_sizeMedium:scale(day) **
## ecosystem_sizeSmall:scale(day) **
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline) *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecsy_M ecsy_S scl(d) sc(__) scl(b) e_M:() e_S:() s():(_
## ecsystm_szM -0.688
## ecsystm_szS -0.584 0.523
## scale(day) 0.177 -0.135 -0.149
## scl(wtr_d_) 0.323 0.022 -0.122 0.143
## scale(bsln) -0.381 0.510 0.440 -0.095 0.034
## ecsyst_M:() -0.098 0.175 0.096 -0.752 0.068 0.107
## ecsyst_S:() -0.150 0.081 0.258 -0.528 0.124 0.073 0.486
## scl(d):(__) 0.383 0.053 0.045 0.005 0.602 0.090 0.054 -0.217
## scl(dy):s() 0.014 0.111 0.095 -0.420 0.202 0.215 0.512 0.367 0.224
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -1.5 0.062 * weak
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_size + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
##
## AIC BIC logLik deviance df.resid
## 11.4 37.1 6.3 -12.6 51
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -3.0 -0.2 -0.1 0.2 5.2
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 2e-01 0.41
## day 5e-04 0.02 -1.00
## Residual 4e-02 0.19
## Number of obs: 63, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.28 0.05 37.35 5.6 2e-06
## ecosystem_sizeMedium -0.17 0.07 40.56 -2.6 0.014
## ecosystem_sizeSmall -0.25 0.08 47.20 -3.1 0.004
## scale(day) 0.10 0.05 19.12 2.2 0.039
## scale(water_addition_ml) 0.06 0.04 54.11 1.4 0.175
## scale(baseline) -0.03 0.03 24.64 -1.0 0.341
## scale(day):scale(water_addition_ml) 0.02 0.04 59.71 0.4 0.678
## scale(day):scale(baseline) -0.01 0.04 15.69 -0.2 0.831
##
## (Intercept) ***
## ecosystem_sizeMedium *
## ecosystem_sizeSmall **
## scale(day) *
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecsy_M ecsy_S scl(d) sc(__) scl(b) s():(_
## ecsystm_szM -0.681
## ecsystm_szS -0.553 0.531
## scale(day) 0.196 -0.007 -0.048
## scl(wtr_d_) 0.357 0.005 -0.160 0.269
## scale(bsln) -0.355 0.488 0.431 -0.013 0.019
## scl(d):(__) 0.378 0.041 0.132 -0.039 0.648 0.098
## scl(dy):s() 0.078 0.020 0.021 -0.009 0.136 0.308 0.230
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
for(eco_type_i in 1:length(ecosystem_type_selected)){
print(ecosystem_type_selected[eco_type_i])
p = ds_ecosystems %>%
filter(ecosystem_type == ecosystem_type_selected[eco_type_i]) %>%
group_by(day) %>%
summarise(Ble = mean(Ble_indiv_per_ml_dominance, na.rm = TRUE),
Cep = mean(Cep_indiv_per_ml_dominance, na.rm = TRUE),
Col = mean(Col_indiv_per_ml_dominance, na.rm = TRUE),
Eug = mean(Eug_indiv_per_ml_dominance, na.rm = TRUE),
Eup = mean(Eup_indiv_per_ml_dominance, na.rm = TRUE),
Lox = mean(Lox_indiv_per_ml_dominance, na.rm = TRUE),
Pau = mean(Pau_indiv_per_ml_dominance, na.rm = TRUE),
Pca = mean(Pca_indiv_per_ml_dominance, na.rm = TRUE),
Spi = mean(Spi_indiv_per_ml_dominance, na.rm = TRUE),
Spi_te = mean(Spi_te_indiv_per_ml_dominance, na.rm = TRUE),
Tet = mean(Tet_indiv_per_ml_dominance, na.rm = TRUE)) %>%
pivot_longer(Ble:Tet, names_to = "species", values_to = "species_indiv_per_ml") %>%
ggplot(aes(x = day,
y = species_indiv_per_ml,
group = interaction(day, species),
color = species)) +
geom_point(position = position_dodge(dodging),
size = treatment_points_size) +
geom_line(aes(group = species),
position = position_dodge(dodging),
linewidth = treatment_lines_linewidth) +
labs(x = axis_names %>%
filter(variable == "day") %>%
pull(axis_name),
y = axis_names %>%
filter(variable == "dominance") %>%
pull(axis_name)) +
coord_cartesian(ylim = c(0, 100))
print(p)
}
## [1] "Small unconnected"
## [1] "Medium unconnected"
## [1] "Large unconnected"
ecosystem_type_selected = c("Small connected to large",
"Small unconnected")
response_variable_selected = "shannon"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
## Warning in qt(conf.interval/2 + 0.5, datac$N - 1): NaNs produced
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -3.4 0.025 ** moderate
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 47.5 67.1 -11.7 23.5 26
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.34 -0.68 0.01 0.74 2.01
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 3e-11 5e-06
## day 5e-14 2e-07 -1.00
## Residual 1e-01 3e-01
## Number of obs: 38, groups: culture_ID, 9
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 0.61 0.10 38.00 5.9
## ecosystem_typeSmall unconnected -0.33 0.14 38.00 -2.4
## scale(day) -0.36 0.09 38.00 -3.9
## scale(water_addition_ml) -0.08 0.11 38.00 -0.8
## scale(baseline) -0.21 0.06 38.00 -3.4
## ecosystem_typeSmall unconnected:scale(day) 0.19 0.17 38.00 1.1
## scale(day):scale(water_addition_ml) -0.05 0.11 38.00 -0.4
## scale(day):scale(baseline) -0.07 0.06 38.00 -1.1
## Pr(>|t|)
## (Intercept) 7e-07 ***
## ecosystem_typeSmall unconnected 0.020 *
## scale(day) 4e-04 ***
## scale(water_addition_ml) 0.439
## scale(baseline) 0.002 **
## ecosystem_typeSmall unconnected:scale(day) 0.279
## scale(day):scale(water_addition_ml) 0.666
## scale(day):scale(baseline) 0.279
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Su scl(d) sc(__) scl(b) e_Su:( s():(_
## ecsystm_tSu -0.521
## scale(day) 0.321 -0.090
## scl(wtr_d_) 0.519 -0.206 0.682
## scale(bsln) 0.332 -0.489 0.095 0.153
## ecsys_Su:() -0.288 0.157 -0.407 -0.045 -0.078
## scl(d):(__) 0.728 -0.128 0.446 0.572 0.169 -0.491
## scl(dy):s() 0.134 -0.033 0.351 0.184 -0.032 -0.394 0.187
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -4.2 0.013 ** moderate
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 46.7 64.7 -12.3 24.7 27
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.30 -0.75 0.04 0.70 2.05
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 3e-16 2e-08
## day 7e-19 8e-10 -1.00
## Residual 1e-01 3e-01
## Number of obs: 38, groups: culture_ID, 9
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.65 0.10 38.00 6.4 2e-07
## ecosystem_typeSmall unconnected -0.36 0.14 38.00 -2.6 0.013
## scale(day) -0.32 0.09 38.00 -3.7 6e-04
## scale(water_addition_ml) -0.08 0.11 38.00 -0.7 0.475
## scale(baseline) -0.21 0.06 38.00 -3.3 0.002
## scale(day):scale(water_addition_ml) 0.01 0.10 38.00 0.1 0.906
## scale(day):scale(baseline) -0.04 0.06 38.00 -0.7 0.481
##
## (Intercept) ***
## ecosystem_typeSmall unconnected *
## scale(day) ***
## scale(water_addition_ml)
## scale(baseline) **
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Su scl(d) sc(__) scl(b) s():(_
## ecsystm_tSu -0.503
## scale(day) 0.233 -0.029
## scl(wtr_d_) 0.529 -0.202 0.727
## scale(bsln) 0.324 -0.484 0.070 0.150
## scl(d):(__) 0.703 -0.059 0.310 0.632 0.151
## scl(dy):s() 0.022 0.033 0.227 0.181 -0.068 -0.008
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "bioarea_mm2_per_ml"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -5.2 0.01 ** moderate
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 22.2 43.6 0.9 -1.8 32
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.70 -0.59 0.04 0.43 2.97
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 1e-01 0.34
## day 2e-04 0.01 -1.00
## Residual 5e-02 0.22
## Number of obs: 44, groups: culture_ID, 9
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 0.47 0.08 17.87 6.0
## ecosystem_typeSmall unconnected -0.40 0.11 10.42 -3.5
## scale(day) -0.37 0.07 17.95 -5.5
## scale(water_addition_ml) -0.04 0.06 35.66 -0.7
## scale(baseline) -0.07 0.06 10.26 -1.3
## ecosystem_typeSmall unconnected:scale(day) 0.31 0.11 15.89 2.8
## scale(day):scale(water_addition_ml) -0.08 0.06 36.05 -1.3
## scale(day):scale(baseline) 0.10 0.05 13.33 1.9
## Pr(>|t|)
## (Intercept) 1e-05 ***
## ecosystem_typeSmall unconnected 0.005 **
## scale(day) 3e-05 ***
## scale(water_addition_ml) 0.476
## scale(baseline) 0.214
## ecosystem_typeSmall unconnected:scale(day) 0.013 *
## scale(day):scale(water_addition_ml) 0.190
## scale(day):scale(baseline) 0.073 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Su scl(d) sc(__) scl(b) e_Su:( s():(_
## ecsystm_tSu -0.658
## scale(day) -0.119 0.167
## scl(wtr_d_) 0.398 -0.205 0.489
## scale(bsln) -0.380 0.576 0.089 -0.088
## ecsys_Su:() 0.021 -0.363 -0.657 -0.190 -0.205
## scl(d):(__) 0.529 -0.066 0.254 0.547 -0.056 -0.425
## scl(dy):s() 0.062 -0.215 -0.420 -0.121 -0.347 0.536 -0.097
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -1.3 0.07 * weak
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 26.1 45.8 -2.1 4.1 33
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.7 -0.5 0.0 0.4 2.9
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 3e-01 0.54
## day 5e-04 0.02 -1.00
## Residual 5e-02 0.22
## Number of obs: 44, groups: culture_ID, 9
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.456 0.081 18.396 5.6 2e-05
## ecosystem_typeSmall unconnected -0.284 0.103 19.028 -2.8 0.012
## scale(day) -0.236 0.063 15.678 -3.8 0.002
## scale(water_addition_ml) -0.001 0.058 33.821 0.0 0.985
## scale(baseline) -0.040 0.056 9.984 -0.7 0.486
## scale(day):scale(water_addition_ml) -0.020 0.060 38.578 -0.3 0.741
## scale(day):scale(baseline) 0.018 0.055 10.690 0.3 0.751
##
## (Intercept) ***
## ecosystem_typeSmall unconnected *
## scale(day) **
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Su scl(d) sc(__) scl(b) s():(_
## ecsystm_tSu -0.683
## scale(day) -0.235 -0.091
## scl(wtr_d_) 0.430 -0.330 0.411
## scale(bsln) -0.358 0.520 -0.059 -0.140
## scl(d):(__) 0.623 -0.296 -0.033 0.535 -0.177
## scl(dy):s() 0.047 -0.025 -0.058 -0.014 -0.420 0.138
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "species_richness"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -9.5 0.001 *** strong
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 143.8 165.2 -59.9 119.8 32
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.2 -0.6 0.1 0.6 2.4
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 2e-05 4e-03
## day 2e-08 1e-04 -1.00
## Residual 9e-01 9e-01
## Number of obs: 44, groups: culture_ID, 9
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 2.50 0.26 43.72 9.7
## ecosystem_typeSmall unconnected -1.54 0.30 42.72 -5.1
## scale(day) -0.95 0.23 44.00 -4.1
## scale(water_addition_ml) -0.07 0.24 43.84 -0.3
## scale(baseline) -0.25 0.15 42.39 -1.7
## ecosystem_typeSmall unconnected:scale(day) 0.42 0.35 44.00 1.2
## scale(day):scale(water_addition_ml) -0.03 0.26 43.87 -0.1
## scale(day):scale(baseline) -0.04 0.15 43.99 -0.3
## Pr(>|t|)
## (Intercept) 2e-12 ***
## ecosystem_typeSmall unconnected 7e-06 ***
## scale(day) 2e-04 ***
## scale(water_addition_ml) 0.8
## scale(baseline) 0.1 .
## ecosystem_typeSmall unconnected:scale(day) 0.2
## scale(day):scale(water_addition_ml) 0.9
## scale(day):scale(baseline) 0.8
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Su scl(d) sc(__) scl(b) e_Su:( s():(_
## ecsystm_tSu -0.545
## scale(day) 0.234 -0.131
## scl(wtr_d_) 0.487 -0.255 0.557
## scale(bsln) 0.058 -0.109 -0.006 -0.009
## ecsys_Su:() -0.310 0.019 -0.542 -0.184 -0.037
## scl(d):(__) 0.666 -0.067 0.281 0.563 0.007 -0.507
## scl(dy):s() -0.051 -0.021 0.025 -0.071 0.001 -0.093 -0.069
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -10 0.001 *** strong
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 143.3 162.9 -60.6 121.3 33
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.13 -0.61 0.08 0.54 2.21
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 2e-08 2e-04
## day 3e-11 6e-06 -1.00
## Residual 9e-01 1e+00
## Number of obs: 44, groups: culture_ID, 9
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 2.60 0.25 44.00 10.4 2e-13
## ecosystem_typeSmall unconnected -1.55 0.31 44.00 -5.1 8e-06
## scale(day) -0.79 0.20 44.00 -4.1 2e-04
## scale(water_addition_ml) -0.01 0.24 44.00 -0.1 1.0
## scale(baseline) -0.24 0.15 44.00 -1.6 0.1
## scale(day):scale(water_addition_ml) 0.14 0.23 44.00 0.6 0.6
## scale(day):scale(baseline) -0.02 0.15 44.00 -0.1 0.9
##
## (Intercept) ***
## ecosystem_typeSmall unconnected ***
## scale(day) ***
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Su scl(d) sc(__) scl(b) s():(_
## ecsystm_tSu -0.568
## scale(day) 0.082 -0.144
## scl(wtr_d_) 0.460 -0.256 0.554
## scale(bsln) 0.049 -0.108 -0.031 -0.016
## scl(d):(__) 0.621 -0.067 0.009 0.554 -0.014
## scl(dy):s() -0.085 -0.019 -0.030 -0.090 -0.003 -0.135
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "evenness_pielou"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
## Warning in qt(conf.interval/2 + 0.5, datac$N - 1): NaNs produced
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
## Warning in qt(conf.interval/2 + 0.5, datac$N - 1): NaNs produced
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -25.6 < 0.001 **** very strong
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## -15.4 0.6 19.7 -39.4 16
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.65 -0.20 -0.02 0.39 2.20
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 2e-01 0.49
## day 4e-04 0.02 -1.00
## Residual 6e-03 0.08
## Number of obs: 28, groups: culture_ID, 9
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 9e-01 6e-02 1e+01 14.5
## ecosystem_typeSmall unconnected -6e-01 1e-01 9e+00 -4.8
## scale(day) 9e-02 6e-02 9e+00 1.4
## scale(water_addition_ml) 1e-01 2e-02 2e+01 5.3
## scale(baseline) -8e-02 6e-02 8e+00 -1.3
## ecosystem_typeSmall unconnected:scale(day) -3e-01 1e-01 9e+00 -2.5
## scale(day):scale(water_addition_ml) 4e-04 3e-02 2e+01 0.0
## scale(day):scale(baseline) -1e-02 6e-02 9e+00 -0.2
## Pr(>|t|)
## (Intercept) 7e-08 ***
## ecosystem_typeSmall unconnected 0.001 **
## scale(day) 0.180
## scale(water_addition_ml) 4e-05 ***
## scale(baseline) 0.217
## ecosystem_typeSmall unconnected:scale(day) 0.033 *
## scale(day):scale(water_addition_ml) 0.991
## scale(day):scale(baseline) 0.863
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Su scl(d) sc(__) scl(b) e_Su:( s():(_
## ecsystm_tSu -0.678
## scale(day) -0.731 0.546
## scl(wtr_d_) 0.121 -0.115 0.244
## scale(bsln) 0.391 -0.677 -0.337 -0.039
## ecsys_Su:() 0.516 -0.825 -0.706 -0.032 0.567
## scl(d):(__) 0.320 0.015 0.069 0.157 -0.020 -0.146
## scl(dy):s() -0.306 0.561 0.404 -0.004 -0.833 -0.687 0.043
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -22.8 < 0.001 **** very strong
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## -12.5 2.1 17.3 -34.5 17
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.62 -0.24 -0.04 0.35 2.18
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 4e-01 0.66
## day 7e-04 0.03 -1.00
## Residual 6e-03 0.08
## Number of obs: 28, groups: culture_ID, 9
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.994 0.062 12.347 16.0 1e-09
## ecosystem_typeSmall unconnected -0.796 0.064 17.379 -12.4 5e-10
## scale(day) -0.021 0.058 9.669 -0.4 0.72
## scale(water_addition_ml) 0.120 0.022 18.027 5.3 4e-05
## scale(baseline) 0.006 0.058 8.980 0.1 0.92
## scale(day):scale(water_addition_ml) -0.002 0.034 18.729 -0.1 0.95
## scale(day):scale(baseline) -0.116 0.058 8.613 -2.0 0.08
##
## (Intercept) ***
## ecosystem_typeSmall unconnected ***
## scale(day)
## scale(water_addition_ml) ***
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline) .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Su scl(d) sc(__) scl(b) s():(_
## ecsystm_tSu -0.450
## scale(day) -0.722 -0.071
## scl(wtr_d_) 0.142 -0.252 0.242
## scale(bsln) 0.050 -0.372 0.132 -0.021
## scl(d):(__) 0.408 -0.190 -0.038 0.158 0.063
## scl(dy):s() 0.109 -0.011 -0.165 -0.026 -0.831 -0.059
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "median_body_area_µm2"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
## Warning in qt(conf.interval/2 + 0.5, datac$N - 1): NaNs produced
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 2.7 0.521 none
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 673.2 692.8 -324.6 649.2 26
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.58 -0.50 -0.07 0.56 1.63
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 1e+05 358
## day 6e+02 24 1.00
## Residual 1e+06 1070
## Number of obs: 38, groups: culture_ID, 9
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 4146 497 12 8.3
## ecosystem_typeSmall unconnected -796 687 9 -1.2
## scale(day) 507 295 23 1.7
## scale(water_addition_ml) 145 356 30 0.4
## scale(baseline) -316 343 8 -0.9
## ecosystem_typeSmall unconnected:scale(day) -54 552 30 -0.1
## scale(day):scale(water_addition_ml) 183 381 33 0.5
## scale(day):scale(baseline) -141 186 17 -0.8
## Pr(>|t|)
## (Intercept) 2e-06 ***
## ecosystem_typeSmall unconnected 0.3
## scale(day) 0.1 .
## scale(water_addition_ml) 0.7
## scale(baseline) 0.4
## ecosystem_typeSmall unconnected:scale(day) 0.9
## scale(day):scale(water_addition_ml) 0.6
## scale(day):scale(baseline) 0.5
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Su scl(d) sc(__) scl(b) e_Su:( s():(_
## ecsystm_tSu -0.574
## scale(day) 0.362 -0.143
## scl(wtr_d_) 0.352 -0.095 0.673
## scale(bsln) -0.046 0.081 0.005 0.022
## ecsys_Su:() -0.283 0.249 -0.335 -0.015 0.028
## scl(d):(__) 0.499 -0.054 0.433 0.582 0.022 -0.500
## scl(dy):s() -0.022 0.044 -0.053 0.001 0.202 0.104 -0.025
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 0.7 0.255 none
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 671.2 689.2 -324.6 649.2 27
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.58 -0.50 -0.07 0.57 1.63
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 1e+05 342
## day 6e+02 25 1.00
## Residual 1e+06 1072
## Number of obs: 38, groups: culture_ID, 9
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 4131 475 12 8.7 1e-06
## ecosystem_typeSmall unconnected -779 663 9 -1.2 0.27
## scale(day) 496 278 26 1.8 0.09
## scale(water_addition_ml) 142 356 30 0.4 0.69
## scale(baseline) -315 342 8 -0.9 0.38
## scale(day):scale(water_addition_ml) 162 330 30 0.5 0.63
## scale(day):scale(baseline) -138 185 18 -0.7 0.46
##
## (Intercept) ***
## ecosystem_typeSmall unconnected
## scale(day) .
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Su scl(d) sc(__) scl(b) s():(_
## ecsystm_tSu -0.541
## scale(day) 0.299 -0.066
## scl(wtr_d_) 0.364 -0.094 0.708
## scale(bsln) -0.039 0.077 0.015 0.023
## scl(d):(__) 0.432 0.085 0.325 0.663 0.042
## scl(dy):s() 0.007 0.019 -0.019 0.003 0.204 0.032
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
for(eco_type_i in 1:length(ecosystem_type_selected)){
print(ecosystem_type_selected[eco_type_i])
p = ds_ecosystems %>%
filter(ecosystem_type == ecosystem_type_selected[eco_type_i]) %>%
group_by(day) %>%
summarise(Ble = mean(Ble_indiv_per_ml_dominance, na.rm = TRUE),
Cep = mean(Cep_indiv_per_ml_dominance, na.rm = TRUE),
Col = mean(Col_indiv_per_ml_dominance, na.rm = TRUE),
Eug = mean(Eug_indiv_per_ml_dominance, na.rm = TRUE),
Eup = mean(Eup_indiv_per_ml_dominance, na.rm = TRUE),
Lox = mean(Lox_indiv_per_ml_dominance, na.rm = TRUE),
Pau = mean(Pau_indiv_per_ml_dominance, na.rm = TRUE),
Pca = mean(Pca_indiv_per_ml_dominance, na.rm = TRUE),
Spi = mean(Spi_indiv_per_ml_dominance, na.rm = TRUE),
Spi_te = mean(Spi_te_indiv_per_ml_dominance, na.rm = TRUE),
Tet = mean(Tet_indiv_per_ml_dominance, na.rm = TRUE)) %>%
pivot_longer(Ble:Tet, names_to = "species", values_to = "species_indiv_per_ml") %>%
ggplot(aes(x = day,
y = species_indiv_per_ml,
group = interaction(day, species),
color = species)) +
geom_point(position = position_dodge(dodging),
size = treatment_points_size) +
geom_line(aes(group = species),
position = position_dodge(dodging),
linewidth = treatment_lines_linewidth) +
labs(x = axis_names %>%
filter(variable == "day") %>%
pull(axis_name),
y = axis_names %>%
filter(variable == "dominance") %>%
pull(axis_name)) +
coord_cartesian(ylim = c(0, 100))
print(p)
}
## [1] "Small connected to large"
## [1] "Small unconnected"
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
"water_addition_ml")
ecosystem_type_selected = c("Small connected to large",
"Small connected to small")
response_variable_selected = "shannon"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 0.9 0.208 none
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 72.3 99.1 -24.1 48.3 57
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.72 -0.69 0.06 0.72 2.26
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 7e-12 3e-06
## day 1e-14 1e-07 -1.00
## Residual 1e-01 3e-01
## Number of obs: 69, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df
## (Intercept) 0.64 0.08 69.00
## ecosystem_typeSmall connected to small -0.16 0.09 69.00
## scale(day) -0.32 0.08 69.00
## scale(water_addition_ml) -0.05 0.06 69.00
## scale(baseline) -0.12 0.04 69.00
## ecosystem_typeSmall connected to small:scale(day) 0.02 0.09 69.00
## scale(day):scale(water_addition_ml) -0.06 0.06 69.00
## scale(day):scale(baseline) -0.07 0.04 69.00
## t value Pr(>|t|)
## (Intercept) 7.9 3e-11 ***
## ecosystem_typeSmall connected to small -1.8 0.079 .
## scale(day) -4.3 7e-05 ***
## scale(water_addition_ml) -0.8 0.419
## scale(baseline) -2.8 0.006 **
## ecosystem_typeSmall connected to small:scale(day) 0.2 0.809
## scale(day):scale(water_addition_ml) -1.0 0.333
## scale(day):scale(baseline) -1.6 0.125
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ec_Scts scl(d) sc(__) scl(b) e_Scts: s():(_
## ecsyst_Scts -0.713
## scale(day) -0.127 0.136
## scl(wtr_d_) 0.144 0.120 0.410
## scale(bsln) 0.234 -0.231 -0.004 0.062
## ecs_Scts:() 0.055 -0.025 -0.690 0.001 -0.033
## scl(d):(__) 0.486 -0.011 0.005 0.480 0.150 -0.023
## scl(dy):s() -0.028 -0.011 0.220 0.079 -0.006 -0.240 -0.036
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -1.1 0.079 * weak
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 70.3 94.9 -24.2 48.3 58
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.74 -0.72 0.03 0.70 2.22
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 1e-10 1e-05
## day 2e-13 5e-07 -1.00
## Residual 1e-01 3e-01
## Number of obs: 69, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 0.64 0.08 69.00 7.9
## ecosystem_typeSmall connected to small -0.16 0.09 69.00 -1.8
## scale(day) -0.31 0.06 69.00 -5.6
## scale(water_addition_ml) -0.05 0.06 69.00 -0.8
## scale(baseline) -0.12 0.04 69.00 -2.8
## scale(day):scale(water_addition_ml) -0.06 0.06 69.00 -1.0
## scale(day):scale(baseline) -0.06 0.04 69.00 -1.5
## Pr(>|t|)
## (Intercept) 3e-11 ***
## ecosystem_typeSmall connected to small 0.080 .
## scale(day) 3e-07 ***
## scale(water_addition_ml) 0.419
## scale(baseline) 0.006 **
## scale(day):scale(water_addition_ml) 0.335
## scale(day):scale(baseline) 0.129
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) e_Scts scl(d) sc(__) scl(b) s():(_
## ecsyst_Scts -0.713
## scale(day) -0.124 0.164
## scl(wtr_d_) 0.145 0.120 0.567
## scale(bsln) 0.236 -0.233 -0.038 0.062
## scl(d):(__) 0.488 -0.012 -0.015 0.480 0.150
## scl(dy):s() -0.016 -0.018 0.078 0.081 -0.014 -0.043
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "bioarea_mm2_per_ml"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 2.2 0.409 none
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 35.9 63.7 -5.9 11.9 63
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.8 -0.6 -0.1 0.5 2.6
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 2e-01 0.49
## day 3e-04 0.02 -1.00
## Residual 5e-02 0.23
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df
## (Intercept) 0.447 0.075 20.439
## ecosystem_typeSmall connected to small -0.105 0.087 16.820
## scale(day) -0.326 0.072 21.253
## scale(water_addition_ml) -0.064 0.042 60.120
## scale(baseline) -0.002 0.041 16.663
## ecosystem_typeSmall connected to small:scale(day) 0.008 0.084 17.423
## scale(day):scale(water_addition_ml) -0.058 0.041 62.518
## scale(day):scale(baseline) 0.002 0.040 17.761
## t value Pr(>|t|)
## (Intercept) 6.0 7e-06 ***
## ecosystem_typeSmall connected to small -1.2 0.2
## scale(day) -4.5 2e-04 ***
## scale(water_addition_ml) -1.5 0.1
## scale(baseline) 0.0 1.0
## ecosystem_typeSmall connected to small:scale(day) 0.1 0.9
## scale(day):scale(water_addition_ml) -1.4 0.2
## scale(day):scale(baseline) 0.1 1.0
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ec_Scts scl(d) sc(__) scl(b) e_Scts: s():(_
## ecsyst_Scts -0.773
## scale(day) -0.491 0.430
## scl(wtr_d_) 0.123 0.068 0.274
## scale(bsln) -0.168 0.217 0.089 0.002
## ecs_Scts:() 0.404 -0.527 -0.783 -0.026 -0.115
## scl(d):(__) 0.321 0.022 -0.010 0.522 0.003 -0.022
## scl(dy):s() 0.054 -0.116 -0.166 -0.054 -0.524 0.218 -0.107
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 0.2 0.182 none
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 33.9 59.4 -5.9 11.9 64
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.9 -0.6 -0.1 0.5 2.7
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 2e-01 0.49
## day 3e-04 0.02 -1.00
## Residual 5e-02 0.23
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 0.444 0.068 31.704 6
## ecosystem_typeSmall connected to small -0.101 0.074 29.924 -1
## scale(day) -0.320 0.045 28.534 -7
## scale(water_addition_ml) -0.064 0.042 60.175 -2
## scale(baseline) -0.001 0.041 17.145 0
## scale(day):scale(water_addition_ml) -0.057 0.041 62.552 -1
## scale(day):scale(baseline) 0.002 0.039 17.744 0
## Pr(>|t|)
## (Intercept) 3e-07 ***
## ecosystem_typeSmall connected to small 0.2
## scale(day) 7e-08 ***
## scale(water_addition_ml) 0.1
## scale(baseline) 1.0
## scale(day):scale(water_addition_ml) 0.2
## scale(day):scale(baseline) 1.0
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) e_Scts scl(d) sc(__) scl(b) s():(_
## ecsyst_Scts -0.720
## scale(day) -0.307 0.034
## scl(wtr_d_) 0.147 0.064 0.407
## scale(bsln) -0.134 0.185 -0.001 -0.001
## scl(d):(__) 0.361 0.012 -0.044 0.522 0.000
## scl(dy):s() -0.038 -0.001 0.008 -0.050 -0.515 -0.105
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "species_richness"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -2 0.049 ** moderate
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 224.3 252.1 -100.1 200.3 63
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.16 -0.63 -0.04 0.73 2.95
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 3e-01 0.55
## day 2e-04 0.01 -1.00
## Residual 8e-01 0.88
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df
## (Intercept) 2.46 0.23 20.10
## ecosystem_typeSmall connected to small -0.73 0.27 15.40
## scale(day) -0.98 0.20 48.20
## scale(water_addition_ml) -0.21 0.16 61.15
## scale(baseline) -0.17 0.13 15.45
## ecosystem_typeSmall connected to small:scale(day) 0.03 0.22 42.31
## scale(day):scale(water_addition_ml) -0.17 0.15 63.95
## scale(day):scale(baseline) 0.03 0.11 42.98
## t value Pr(>|t|)
## (Intercept) 10.5 1e-09 ***
## ecosystem_typeSmall connected to small -2.7 0.02 *
## scale(day) -4.9 1e-05 ***
## scale(water_addition_ml) -1.3 0.19
## scale(baseline) -1.4 0.19
## ecosystem_typeSmall connected to small:scale(day) 0.1 0.91
## scale(day):scale(water_addition_ml) -1.1 0.26
## scale(day):scale(baseline) 0.3 0.77
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ec_Scts scl(d) sc(__) scl(b) e_Scts: s():(_
## ecsyst_Scts -0.745
## scale(day) -0.127 0.117
## scl(wtr_d_) 0.146 0.091 0.355
## scale(bsln) -0.045 0.112 0.013 0.066
## ecs_Scts:() 0.081 -0.112 -0.744 -0.019 -0.013
## scl(d):(__) 0.374 0.039 -0.019 0.534 0.100 -0.011
## scl(dy):s() -0.040 -0.008 -0.035 0.020 -0.119 0.107 -0.116
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -4 0.014 ** moderate
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 222.3 247.8 -100.2 200.3 64
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.15 -0.62 -0.04 0.72 2.91
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 3e-01 0.55
## day 2e-04 0.01 -1.00
## Residual 8e-01 0.88
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 2.45 0.23 20.59 10.5
## ecosystem_typeSmall connected to small -0.72 0.27 15.94 -2.7
## scale(day) -0.97 0.13 54.56 -7.2
## scale(water_addition_ml) -0.21 0.16 61.15 -1.3
## scale(baseline) -0.17 0.13 15.46 -1.4
## scale(day):scale(water_addition_ml) -0.17 0.15 63.94 -1.1
## scale(day):scale(baseline) 0.03 0.11 42.93 0.3
## Pr(>|t|)
## (Intercept) 1e-09 ***
## ecosystem_typeSmall connected to small 0.02 *
## scale(day) 2e-09 ***
## scale(water_addition_ml) 0.19
## scale(baseline) 0.19
## scale(day):scale(water_addition_ml) 0.26
## scale(day):scale(baseline) 0.77
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) e_Scts scl(d) sc(__) scl(b) s():(_
## ecsyst_Scts -0.743
## scale(day) -0.101 0.050
## scl(wtr_d_) 0.148 0.090 0.510
## scale(bsln) -0.044 0.111 0.005 0.066
## scl(d):(__) 0.376 0.038 -0.041 0.534 0.100
## scl(dy):s() -0.049 0.004 0.067 0.022 -0.118 -0.115
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "evenness_pielou"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -4 0.018 ** moderate
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## -3.1 20.3 13.6 -27.1 40
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -3.6 -0.5 0.0 0.6 2.3
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 1e-02 0.119
## day 6e-05 0.008 -1.00
## Residual 3e-02 0.181
## Number of obs: 52, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df
## (Intercept) 0.900 0.053 38.132
## ecosystem_typeSmall connected to small -0.185 0.062 32.657
## scale(day) -0.036 0.059 23.902
## scale(water_addition_ml) -0.007 0.039 48.900
## scale(baseline) -0.030 0.030 34.831
## ecosystem_typeSmall connected to small:scale(day) -0.177 0.069 17.282
## scale(day):scale(water_addition_ml) 0.021 0.039 48.653
## scale(day):scale(baseline) -0.074 0.031 17.566
## t value Pr(>|t|)
## (Intercept) 17.0 <2e-16 ***
## ecosystem_typeSmall connected to small -3.0 0.005 **
## scale(day) -0.6 0.547
## scale(water_addition_ml) -0.2 0.861
## scale(baseline) -1.0 0.309
## ecosystem_typeSmall connected to small:scale(day) -2.6 0.019 *
## scale(day):scale(water_addition_ml) 0.5 0.599
## scale(day):scale(baseline) -2.3 0.031 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ec_Scts scl(d) sc(__) scl(b) e_Scts: s():(_
## ecsyst_Scts -0.735
## scale(day) 0.128 -0.069
## scl(wtr_d_) 0.113 0.125 0.408
## scale(bsln) 0.311 -0.445 -0.002 -0.137
## ecs_Scts:() -0.082 0.133 -0.775 -0.003 -0.045
## scl(d):(__) 0.424 0.054 0.064 0.435 -0.059 0.081
## scl(dy):s() 0.058 -0.049 0.263 -0.044 0.101 -0.432 0.004
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -0.9 0.089 * weak
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 0.0 21.5 11.0 -22.0 41
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -3.9 -0.5 0.1 0.7 1.6
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 5e-02 0.22
## day 2e-04 0.01 -1.00
## Residual 3e-02 0.18
## Number of obs: 52, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 0.875 0.056 34.676 15.7
## ecosystem_typeSmall connected to small -0.132 0.064 35.136 -2.1
## scale(day) -0.144 0.044 26.006 -3.3
## scale(water_addition_ml) 0.008 0.041 50.507 0.2
## scale(baseline) -0.044 0.032 23.460 -1.4
## scale(day):scale(water_addition_ml) 0.039 0.041 50.278 0.9
## scale(day):scale(baseline) -0.111 0.034 17.297 -3.3
## Pr(>|t|)
## (Intercept) <2e-16 ***
## ecosystem_typeSmall connected to small 0.046 *
## scale(day) 0.003 **
## scale(water_addition_ml) 0.841
## scale(baseline) 0.181
## scale(day):scale(water_addition_ml) 0.350
## scale(day):scale(baseline) 0.004 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) e_Scts scl(d) sc(__) scl(b) s():(_
## ecsyst_Scts -0.725
## scale(day) 0.183 0.062
## scl(wtr_d_) 0.140 0.134 0.597
## scale(bsln) 0.297 -0.443 -0.072 -0.145
## scl(d):(__) 0.432 0.043 0.199 0.486 -0.072
## scl(dy):s() 0.020 -0.009 -0.125 -0.048 0.263 0.027
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "median_body_area_µm2"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
## Warning: Model failed to converge with 1 negative eigenvalue: -1.2e+00
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -3.8 0.02 ** moderate
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 1198.6 1225.4 -587.3 1174.6 57
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.7 -0.5 0.2 0.6 2.2
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 2e+04 151
## day 2e+02 16 1.00
## Residual 1e+06 1131
## Number of obs: 69, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df
## (Intercept) 4216 336 19
## ecosystem_typeSmall connected to small -1019 387 15
## scale(day) 314 252 43
## scale(water_addition_ml) -143 211 58
## scale(baseline) -202 188 14
## ecosystem_typeSmall connected to small:scale(day) -599 294 39
## scale(day):scale(water_addition_ml) 201 207 61
## scale(day):scale(baseline) -211 138 38
## t value Pr(>|t|)
## (Intercept) 12.6 1e-10 ***
## ecosystem_typeSmall connected to small -2.6 0.02 *
## scale(day) 1.2 0.22
## scale(water_addition_ml) -0.7 0.50
## scale(baseline) -1.1 0.30
## ecosystem_typeSmall connected to small:scale(day) -2.0 0.05 *
## scale(day):scale(water_addition_ml) 1.0 0.34
## scale(day):scale(baseline) -1.5 0.13
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ec_Scts scl(d) sc(__) scl(b) e_Scts: s():(_
## ecsyst_Scts -0.751
## scale(day) 0.010 0.021
## scl(wtr_d_) 0.133 0.086 0.407
## scale(bsln) -0.151 0.184 0.001 -0.002
## ecs_Scts:() -0.053 0.088 -0.684 -0.012 0.023
## scl(d):(__) 0.386 -0.005 0.044 0.512 -0.033 -0.067
## scl(dy):s() -0.030 0.019 -0.145 -0.051 0.042 0.202 -0.067
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -1.8 0.05 * weak
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 1200.5 1225.1 -589.3 1178.5 58
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.8 -0.7 0.1 0.6 2.3
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 0e+00 0
## day 5e+02 23 NaN
## Residual 1e+06 1166
## Number of obs: 69, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 4157 341 20 12.2
## ecosystem_typeSmall connected to small -919 391 16 -2.4
## scale(day) -39 191 48 -0.2
## scale(water_addition_ml) -149 218 60 -0.7
## scale(baseline) -190 191 14 -1.0
## scale(day):scale(water_addition_ml) 170 214 62 0.8
## scale(day):scale(baseline) -154 142 35 -1.1
## Pr(>|t|)
## (Intercept) 8e-11 ***
## ecosystem_typeSmall connected to small 0.03 *
## scale(day) 0.84
## scale(water_addition_ml) 0.50
## scale(baseline) 0.34
## scale(day):scale(water_addition_ml) 0.43
## scale(day):scale(baseline) 0.28
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) e_Scts scl(d) sc(__) scl(b) s():(_
## ecsyst_Scts -0.746
## scale(day) -0.014 0.109
## scl(wtr_d_) 0.137 0.090 0.543
## scale(bsln) -0.149 0.181 0.022 -0.002
## scl(d):(__) 0.388 0.004 0.000 0.517 -0.032
## scl(dy):s() -0.019 0.001 -0.010 -0.049 0.083 -0.054
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
for(eco_type_i in 1:length(ecosystem_type_selected)){
print(ecosystem_type_selected[eco_type_i])
p = ds_ecosystems %>%
filter(ecosystem_type == ecosystem_type_selected[eco_type_i]) %>%
group_by(day) %>%
summarise(Ble = mean(Ble_indiv_per_ml_dominance, na.rm = TRUE),
Cep = mean(Cep_indiv_per_ml_dominance, na.rm = TRUE),
Col = mean(Col_indiv_per_ml_dominance, na.rm = TRUE),
Eug = mean(Eug_indiv_per_ml_dominance, na.rm = TRUE),
Eup = mean(Eup_indiv_per_ml_dominance, na.rm = TRUE),
Lox = mean(Lox_indiv_per_ml_dominance, na.rm = TRUE),
Pau = mean(Pau_indiv_per_ml_dominance, na.rm = TRUE),
Pca = mean(Pca_indiv_per_ml_dominance, na.rm = TRUE),
Spi = mean(Spi_indiv_per_ml_dominance, na.rm = TRUE),
Spi_te = mean(Spi_te_indiv_per_ml_dominance, na.rm = TRUE),
Tet = mean(Tet_indiv_per_ml_dominance, na.rm = TRUE)) %>%
pivot_longer(Ble:Tet, names_to = "species", values_to = "species_indiv_per_ml") %>%
ggplot(aes(x = day,
y = species_indiv_per_ml,
group = interaction(day, species),
color = species)) +
geom_point(position = position_dodge(dodging),
size = treatment_points_size) +
geom_line(aes(group = species),
position = position_dodge(dodging),
linewidth = treatment_lines_linewidth) +
labs(x = axis_names %>%
filter(variable == "day") %>%
pull(axis_name),
y = axis_names %>%
filter(variable == "dominance") %>%
pull(axis_name)) +
coord_cartesian(ylim = c(0, 100))
print(p)
}
## [1] "Small connected to large"
## [1] "Small connected to small"
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
"water_addition_ml")
ecosystem_type_selected = c("Small connected to small",
"Small unconnected")
response_variable_selected = "shannon"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
## Warning in qt(conf.interval/2 + 0.5, datac$N - 1): NaNs produced
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -3.9 0.019 ** moderate
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 54.1 78.6 -15.0 30.1 45
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.47 -0.66 -0.04 0.64 2.11
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 1e-01 0.34
## day 3e-04 0.02 -0.94
## Residual 8e-02 0.29
## Number of obs: 57, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 0.56 0.07 23.06 7.9
## ecosystem_typeSmall unconnected -0.33 0.12 15.25 -2.7
## scale(day) -0.29 0.06 16.77 -4.6
## scale(water_addition_ml) 0.05 0.07 38.19 0.7
## scale(baseline) -0.05 0.05 10.99 -1.0
## ecosystem_typeSmall unconnected:scale(day) 0.15 0.13 22.83 1.1
## scale(day):scale(water_addition_ml) 0.05 0.06 45.04 0.8
## scale(day):scale(baseline) -0.04 0.05 10.34 -0.8
## Pr(>|t|)
## (Intercept) 5e-08 ***
## ecosystem_typeSmall unconnected 0.02 *
## scale(day) 3e-04 ***
## scale(water_addition_ml) 0.51
## scale(baseline) 0.32
## ecosystem_typeSmall unconnected:scale(day) 0.26
## scale(day):scale(water_addition_ml) 0.44
## scale(day):scale(baseline) 0.46
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Su scl(d) sc(__) scl(b) e_Su:( s():(_
## ecsystm_tSu -0.444
## scale(day) 0.177 -0.132
## scl(wtr_d_) 0.405 -0.215 0.536
## scale(bsln) 0.163 -0.251 -0.008 0.040
## ecsys_Su:() -0.153 0.151 -0.293 0.046 -0.067
## scl(d):(__) 0.598 -0.059 0.177 0.524 0.088 -0.282
## scl(dy):s() -0.079 -0.041 0.104 -0.013 0.052 -0.159 -0.113
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -4.7 0.009 *** strong
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 53.3 75.7 -15.6 31.3 46
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.4 -0.6 0.0 0.6 2.1
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 1e-01 0.36
## day 4e-04 0.02 -0.97
## Residual 9e-02 0.29
## Number of obs: 57, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.57 0.07 27.16 8.4 5e-09
## ecosystem_typeSmall unconnected -0.36 0.12 17.81 -3.1 0.007
## scale(day) -0.27 0.06 21.86 -4.3 3e-04
## scale(water_addition_ml) 0.04 0.07 37.96 0.6 0.570
## scale(baseline) -0.05 0.05 12.44 -1.0 0.343
## scale(day):scale(water_addition_ml) 0.07 0.06 45.98 1.1 0.278
## scale(day):scale(baseline) -0.03 0.05 10.61 -0.5 0.600
##
## (Intercept) ***
## ecosystem_typeSmall unconnected **
## scale(day) ***
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Su scl(d) sc(__) scl(b) s():(_
## ecsystm_tSu -0.416
## scale(day) 0.160 -0.102
## scl(wtr_d_) 0.440 -0.239 0.567
## scale(bsln) 0.153 -0.246 -0.028 0.047
## scl(d):(__) 0.613 -0.013 0.099 0.561 0.076
## scl(dy):s() -0.108 -0.020 0.061 -0.006 0.069 -0.164
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "bioarea_mm2_per_ml"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -3.4 0.024 ** moderate
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 3.4 30.2 10.3 -20.6 57
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.43 -0.46 -0.09 0.45 2.92
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 1e-01 0.37
## day 2e-04 0.01 -1.00
## Residual 4e-02 0.19
## Number of obs: 69, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 0.36 0.04 28.96 8.2
## ecosystem_typeSmall unconnected -0.21 0.07 18.61 -2.9
## scale(day) -0.30 0.04 21.50 -7.4
## scale(water_addition_ml) -0.02 0.04 55.27 -0.6
## scale(baseline) 0.02 0.03 16.08 0.7
## ecosystem_typeSmall unconnected:scale(day) 0.16 0.08 20.64 2.1
## scale(day):scale(water_addition_ml) -0.04 0.04 57.26 -1.1
## scale(day):scale(baseline) -0.01 0.03 16.17 -0.3
## Pr(>|t|)
## (Intercept) 5e-09 ***
## ecosystem_typeSmall unconnected 0.009 **
## scale(day) 3e-07 ***
## scale(water_addition_ml) 0.552
## scale(baseline) 0.524
## ecosystem_typeSmall unconnected:scale(day) 0.051 .
## scale(day):scale(water_addition_ml) 0.277
## scale(day):scale(baseline) 0.742
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Su scl(d) sc(__) scl(b) e_Su:( s():(_
## ecsystm_tSu -0.499
## scale(day) -0.281 0.129
## scl(wtr_d_) 0.391 -0.241 0.393
## scale(bsln) -0.051 0.099 0.012 -0.025
## ecsys_Su:() 0.038 -0.413 -0.442 -0.111 -0.056
## scl(d):(__) 0.530 -0.077 0.105 0.565 -0.018 -0.339
## scl(dy):s() -0.065 -0.045 -0.067 -0.106 -0.481 0.130 -0.155
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -1.5 0.062 * weak
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 5.3 29.9 8.3 -16.7 58
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.45 -0.51 -0.04 0.45 2.90
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 2e-01 0.43
## day 3e-04 0.02 -1.00
## Residual 4e-02 0.19
## Number of obs: 69, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.35 0.04 27.59 7.9 2e-08
## ecosystem_typeSmall unconnected -0.15 0.07 31.05 -2.2 0.03
## scale(day) -0.26 0.04 21.22 -6.5 2e-06
## scale(water_addition_ml) -0.02 0.04 53.67 -0.4 0.69
## scale(baseline) 0.02 0.03 13.67 0.8 0.46
## scale(day):scale(water_addition_ml) -0.02 0.04 61.09 -0.6 0.56
## scale(day):scale(baseline) -0.02 0.04 13.61 -0.5 0.60
##
## (Intercept) ***
## ecosystem_typeSmall unconnected *
## scale(day) ***
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Su scl(d) sc(__) scl(b) s():(_
## ecsystm_tSu -0.525
## scale(day) -0.335 -0.061
## scl(wtr_d_) 0.399 -0.325 0.359
## scale(bsln) -0.047 0.081 -0.014 -0.031
## scl(d):(__) 0.581 -0.262 -0.055 0.563 -0.039
## scl(dy):s() -0.067 0.009 -0.007 -0.085 -0.526 -0.109
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "species_richness"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -6.4 0.006 *** strong
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 183.2 210.0 -79.6 159.2 57
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.01 -0.57 -0.04 0.52 2.74
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 6e-01 0.78
## day 9e-04 0.03 -0.96
## Residual 5e-01 0.71
## Number of obs: 69, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 1.84 0.16 27.01 11.6
## ecosystem_typeSmall unconnected -0.95 0.26 16.33 -3.7
## scale(day) -0.92 0.13 19.66 -7.0
## scale(water_addition_ml) -0.10 0.15 54.77 -0.7
## scale(baseline) 0.06 0.11 13.82 0.5
## ecosystem_typeSmall unconnected:scale(day) 0.34 0.25 17.68 1.4
## scale(day):scale(water_addition_ml) -0.05 0.14 57.52 -0.3
## scale(day):scale(baseline) 0.08 0.11 13.99 0.7
## Pr(>|t|)
## (Intercept) 6e-12 ***
## ecosystem_typeSmall unconnected 0.002 **
## scale(day) 1e-06 ***
## scale(water_addition_ml) 0.504
## scale(baseline) 0.600
## ecosystem_typeSmall unconnected:scale(day) 0.186
## scale(day):scale(water_addition_ml) 0.736
## scale(day):scale(baseline) 0.480
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Su scl(d) sc(__) scl(b) e_Su:( s():(_
## ecsystm_tSu -0.496
## scale(day) -0.015 -0.043
## scl(wtr_d_) 0.430 -0.242 0.446
## scale(bsln) 0.076 -0.196 -0.038 -0.047
## ecsys_Su:() -0.104 -0.113 -0.404 -0.092 0.006
## scl(d):(__) 0.570 -0.082 0.110 0.596 -0.026 -0.331
## scl(dy):s() -0.164 0.031 0.057 -0.178 -0.146 -0.136 -0.255
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -6.6 0.003 *** strong
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 183.0 207.5 -80.5 161.0 58
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.80 -0.62 -0.05 0.53 2.65
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 0.783 0.89
## day 0.001 0.04 -0.96
## Residual 0.510 0.71
## Number of obs: 69, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 1.867 0.159 26.134 11.7 6e-12
## ecosystem_typeSmall unconnected -0.930 0.258 16.575 -3.6 0.002
## scale(day) -0.850 0.126 23.458 -6.7 7e-07
## scale(water_addition_ml) -0.084 0.149 53.854 -0.6 0.575
## scale(baseline) 0.062 0.113 13.814 0.6 0.590
## scale(day):scale(water_addition_ml) 0.008 0.138 59.613 0.1 0.956
## scale(day):scale(baseline) 0.099 0.110 13.996 0.9 0.383
##
## (Intercept) ***
## ecosystem_typeSmall unconnected **
## scale(day) ***
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Su scl(d) sc(__) scl(b) s():(_
## ecsystm_tSu -0.508
## scale(day) -0.038 -0.098
## scl(wtr_d_) 0.432 -0.250 0.431
## scale(bsln) 0.075 -0.197 -0.038 -0.050
## scl(d):(__) 0.573 -0.114 -0.023 0.610 -0.030
## scl(dy):s() -0.176 0.012 0.001 -0.189 -0.109 -0.310
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "evenness_pielou"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
## Warning in qt(conf.interval/2 + 0.5, datac$N - 1): NaNs produced
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
## Warning in qt(conf.interval/2 + 0.5, datac$N - 1): NaNs produced
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -2.5 0.038 ** moderate
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 20.4 41.8 1.8 -3.6 32
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.94 -0.48 -0.01 0.69 2.20
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 8e-04 0.028
## day 3e-06 0.002 -1.00
## Residual 5e-02 0.232
## Number of obs: 44, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 0.68 0.05 43.84 12.7
## ecosystem_typeSmall unconnected -0.24 0.09 41.62 -2.5
## scale(day) -0.26 0.05 21.31 -5.0
## scale(water_addition_ml) -0.02 0.05 40.44 -0.3
## scale(baseline) -0.05 0.04 42.55 -1.3
## ecosystem_typeSmall unconnected:scale(day) -0.06 0.09 28.80 -0.7
## scale(day):scale(water_addition_ml) 0.01 0.05 43.00 0.2
## scale(day):scale(baseline) -0.06 0.04 15.40 -1.7
## Pr(>|t|)
## (Intercept) 3e-16 ***
## ecosystem_typeSmall unconnected 0.02 *
## scale(day) 6e-05 ***
## scale(water_addition_ml) 0.74
## scale(baseline) 0.18
## ecosystem_typeSmall unconnected:scale(day) 0.49
## scale(day):scale(water_addition_ml) 0.83
## scale(day):scale(baseline) 0.12
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Su scl(d) sc(__) scl(b) e_Su:( s():(_
## ecsystm_tSu -0.465
## scale(day) 0.293 -0.274
## scl(wtr_d_) 0.370 -0.402 0.618
## scale(bsln) 0.101 -0.190 0.027 -0.036
## ecsys_Su:() -0.277 -0.037 -0.459 -0.137 -0.033
## scl(d):(__) 0.634 -0.109 0.266 0.349 0.042 -0.397
## scl(dy):s() 0.112 -0.031 0.054 0.057 -0.049 -0.205 0.116
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -4 0.014 ** moderate
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 18.9 38.5 1.6 -3.1 33
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.9 -0.5 -0.1 0.7 2.3
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 4e-11 6e-06
## day 1e-13 3e-07 -1.00
## Residual 5e-02 2e-01
## Number of obs: 44, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.665 0.051 44.000 13.0 <2e-16
## ecosystem_typeSmall unconnected -0.242 0.095 44.000 -2.5 0.01
## scale(day) -0.280 0.047 44.000 -6.0 4e-07
## scale(water_addition_ml) -0.022 0.051 44.000 -0.4 0.66
## scale(baseline) -0.050 0.037 44.000 -1.4 0.18
## scale(day):scale(water_addition_ml) -0.004 0.048 44.000 -0.1 0.94
## scale(day):scale(baseline) -0.067 0.036 44.000 -1.8 0.07
##
## (Intercept) ***
## ecosystem_typeSmall unconnected *
## scale(day) ***
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline) .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Su scl(d) sc(__) scl(b) s():(_
## ecsystm_tSu -0.495
## scale(day) 0.192 -0.328
## scl(wtr_d_) 0.347 -0.412 0.632
## scale(bsln) 0.096 -0.191 0.014 -0.041
## scl(d):(__) 0.594 -0.136 0.103 0.323 0.031
## scl(dy):s() 0.060 -0.040 -0.046 0.030 -0.060 0.039
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "median_body_area_µm2"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
## Warning in qt(conf.interval/2 + 0.5, datac$N - 1): NaNs produced
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 1.7 0.324 none
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 984.7 1009.2 -480.3 960.7 45
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.65 -0.62 0.03 0.82 1.43
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 3e+06 1865
## day 6e+03 80 -1.00
## Residual 1e+06 1000
## Number of obs: 57, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 3163 240 30 13.2
## ecosystem_typeSmall unconnected 361 406 21 0.9
## scale(day) -269 230 19 -1.2
## scale(water_addition_ml) -263 232 44 -1.1
## scale(baseline) 126 172 15 0.7
## ecosystem_typeSmall unconnected:scale(day) 472 462 25 1.0
## scale(day):scale(water_addition_ml) 148 222 48 0.7
## scale(day):scale(baseline) -156 173 11 -0.9
## Pr(>|t|)
## (Intercept) 7e-14 ***
## ecosystem_typeSmall unconnected 0.4
## scale(day) 0.3
## scale(water_addition_ml) 0.3
## scale(baseline) 0.5
## ecosystem_typeSmall unconnected:scale(day) 0.3
## scale(day):scale(water_addition_ml) 0.5
## scale(day):scale(baseline) 0.4
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Su scl(d) sc(__) scl(b) e_Su:( s():(_
## ecsystm_tSu -0.415
## scale(day) -0.167 0.076
## scl(wtr_d_) 0.380 -0.198 0.490
## scale(bsln) -0.018 -0.077 0.005 -0.034
## ecsys_Su:() 0.016 -0.245 -0.301 0.076 0.083
## scl(d):(__) 0.582 -0.014 0.153 0.490 -0.046 -0.280
## scl(dy):s() -0.042 0.067 0.013 -0.059 -0.467 -0.087 -0.098
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 0.8 0.264 none
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 983.7 1006.2 -480.8 961.7 46
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.69 -0.61 0.07 0.76 1.44
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 4e+06 1973
## day 7e+03 84 -1.00
## Residual 1e+06 1000
## Number of obs: 57, groups: culture_ID, 14
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 3158 244 28 12.9 2e-13
## ecosystem_typeSmall unconnected 475 400 24 1.2 0.2
## scale(day) -199 223 22 -0.9 0.4
## scale(water_addition_ml) -280 232 44 -1.2 0.2
## scale(baseline) 111 176 14 0.6 0.5
## scale(day):scale(water_addition_ml) 216 214 49 1.0 0.3
## scale(day):scale(baseline) -141 176 11 -0.8 0.4
##
## (Intercept) ***
## ecosystem_typeSmall unconnected
## scale(day)
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Su scl(d) sc(__) scl(b) s():(_
## ecsystm_tSu -0.427
## scale(day) -0.197 0.010
## scl(wtr_d_) 0.371 -0.181 0.532
## scale(bsln) -0.020 -0.059 0.032 -0.040
## scl(d):(__) 0.605 -0.096 0.070 0.531 -0.022
## scl(dy):s() -0.038 0.049 -0.016 -0.051 -0.491 -0.127
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
for(eco_type_i in 1:length(ecosystem_type_selected)){
print(ecosystem_type_selected[eco_type_i])
p = ds_ecosystems %>%
filter(ecosystem_type == ecosystem_type_selected[eco_type_i]) %>%
group_by(day) %>%
summarise(Ble = mean(Ble_indiv_per_ml_dominance, na.rm = TRUE),
Cep = mean(Cep_indiv_per_ml_dominance, na.rm = TRUE),
Col = mean(Col_indiv_per_ml_dominance, na.rm = TRUE),
Eug = mean(Eug_indiv_per_ml_dominance, na.rm = TRUE),
Eup = mean(Eup_indiv_per_ml_dominance, na.rm = TRUE),
Lox = mean(Lox_indiv_per_ml_dominance, na.rm = TRUE),
Pau = mean(Pau_indiv_per_ml_dominance, na.rm = TRUE),
Pca = mean(Pca_indiv_per_ml_dominance, na.rm = TRUE),
Spi = mean(Spi_indiv_per_ml_dominance, na.rm = TRUE),
Spi_te = mean(Spi_te_indiv_per_ml_dominance, na.rm = TRUE),
Tet = mean(Tet_indiv_per_ml_dominance, na.rm = TRUE)) %>%
pivot_longer(Ble:Tet, names_to = "species", values_to = "species_indiv_per_ml") %>%
ggplot(aes(x = day,
y = species_indiv_per_ml,
group = interaction(day, species),
color = species)) +
geom_point(position = position_dodge(dodging),
size = treatment_points_size) +
geom_line(aes(group = species),
position = position_dodge(dodging),
linewidth = treatment_lines_linewidth) +
labs(x = axis_names %>%
filter(variable == "day") %>%
pull(axis_name),
y = axis_names %>%
filter(variable == "dominance") %>%
pull(axis_name)) +
coord_cartesian(ylim = c(0, 100))
print(p)
}
## [1] "Small connected to small"
## [1] "Small unconnected"
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
"water_addition_ml")
ecosystem_type_selected = c("Large connected to small",
"Large unconnected")
response_variable_selected = "shannon"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 2.9 0.59 none
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 35.3 58.2 -5.6 11.3 38
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.2 -0.8 -0.1 0.7 1.7
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 2e-01 0.48
## day 7e-04 0.03 -1.00
## Residual 6e-02 0.24
## Number of obs: 50, groups: culture_ID, 10
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 1.348 0.054 27.036 25.0
## ecosystem_typeLarge unconnected 0.054 0.077 26.588 0.7
## scale(day) 0.079 0.088 11.220 0.9
## scale(water_addition_ml) -0.080 0.048 48.585 -1.7
## scale(baseline) 0.043 0.037 24.975 1.2
## ecosystem_typeLarge unconnected:scale(day) -0.064 0.121 10.049 -0.5
## scale(day):scale(water_addition_ml) -0.071 0.046 45.231 -1.5
## scale(day):scale(baseline) 0.008 0.059 9.103 0.1
## Pr(>|t|)
## (Intercept) <2e-16 ***
## ecosystem_typeLarge unconnected 0.5
## scale(day) 0.4
## scale(water_addition_ml) 0.1
## scale(baseline) 0.3
## ecosystem_typeLarge unconnected:scale(day) 0.6
## scale(day):scale(water_addition_ml) 0.1
## scale(day):scale(baseline) 0.9
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Lu scl(d) sc(__) scl(b) e_Lu:( s():(_
## ecsystm_tLu -0.661
## scale(day) 0.158 -0.171
## scl(wtr_d_) -0.053 0.292 0.037
## scale(bsln) -0.040 0.044 -0.024 -0.097
## ecsys_Lu:() -0.131 0.294 -0.712 0.119 0.013
## scl(d):(__) 0.223 0.149 -0.268 0.469 -0.027 0.236
## scl(dy):s() -0.027 0.016 -0.035 -0.010 0.274 0.062 -0.048
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 1.2 0.377 none
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 33.5 54.6 -5.8 11.5 39
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.2 -0.8 -0.1 0.7 1.8
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 2e-01 0.49
## day 7e-04 0.03 -1.00
## Residual 6e-02 0.24
## Number of obs: 50, groups: culture_ID, 10
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 1.34 0.05 31.44 25.1 <2e-16
## ecosystem_typeLarge unconnected 0.07 0.07 37.86 0.9 0.4
## scale(day) 0.05 0.06 10.63 0.8 0.5
## scale(water_addition_ml) -0.08 0.05 48.97 -1.6 0.1
## scale(baseline) 0.04 0.04 25.05 1.2 0.3
## scale(day):scale(water_addition_ml) -0.07 0.05 47.37 -1.5 0.2
## scale(day):scale(baseline) 0.01 0.06 8.87 0.2 0.9
##
## (Intercept) ***
## ecosystem_typeLarge unconnected
## scale(day)
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Lu scl(d) sc(__) scl(b) s():(_
## ecsystm_tLu -0.657
## scale(day) 0.090 0.058
## scl(wtr_d_) -0.039 0.271 0.174
## scale(bsln) -0.039 0.042 -0.021 -0.099
## scl(d):(__) 0.263 0.086 -0.146 0.456 -0.031
## scl(dy):s() -0.019 -0.002 0.013 -0.018 0.271 -0.064
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "bioarea_mm2_per_ml"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -7.4 0.003 *** strong
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 126.5 149.5 -51.3 102.5 38
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.92 -0.66 -0.08 0.56 2.36
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 4e-01 0.60
## day 5e-04 0.02 -1.00
## Residual 4e-01 0.65
## Number of obs: 50, groups: culture_ID, 10
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 1.821 0.156 12.624 11.7
## ecosystem_typeLarge unconnected 1.004 0.219 12.633 4.6
## scale(day) -0.847 0.161 24.418 -5.2
## scale(water_addition_ml) 0.003 0.115 40.495 0.0
## scale(baseline) 0.068 0.108 11.532 0.6
## ecosystem_typeLarge unconnected:scale(day) -0.346 0.213 21.615 -1.6
## scale(day):scale(water_addition_ml) -0.109 0.117 46.161 -0.9
## scale(day):scale(baseline) 0.192 0.104 19.439 1.9
## Pr(>|t|)
## (Intercept) 4e-08 ***
## ecosystem_typeLarge unconnected 6e-04 ***
## scale(day) 2e-05 ***
## scale(water_addition_ml) 0.98
## scale(baseline) 0.54
## ecosystem_typeLarge unconnected:scale(day) 0.12
## scale(day):scale(water_addition_ml) 0.35
## scale(day):scale(baseline) 0.08 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Lu scl(d) sc(__) scl(b) e_Lu:( s():(_
## ecsystm_tLu -0.675
## scale(day) -0.297 0.140
## scl(wtr_d_) -0.068 0.243 0.095
## scale(bsln) 0.061 -0.042 -0.040 0.082
## ecsys_Lu:() 0.200 -0.149 -0.719 0.125 0.049
## scl(d):(__) 0.222 0.093 -0.401 0.359 0.109 0.331
## scl(dy):s() 0.016 0.049 -0.007 0.146 -0.169 -0.002 0.174
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -7 0.003 *** strong
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 126.9 147.9 -52.5 104.9 39
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.93 -0.65 -0.02 0.55 2.26
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 0.747 0.86
## day 0.001 0.03 -1.00
## Residual 0.419 0.65
## Number of obs: 50, groups: culture_ID, 10
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 1.895 0.159 15.121 11.9 4e-09
## ecosystem_typeLarge unconnected 0.909 0.223 17.201 4.1 8e-04
## scale(day) -1.046 0.122 16.468 -8.6 2e-07
## scale(water_addition_ml) 0.006 0.115 40.603 0.0 1.0
## scale(baseline) 0.078 0.114 10.515 0.7 0.5
## scale(day):scale(water_addition_ml) -0.040 0.112 48.338 -0.4 0.7
## scale(day):scale(baseline) 0.191 0.113 13.321 1.7 0.1
##
## (Intercept) ***
## ecosystem_typeLarge unconnected ***
## scale(day) ***
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Lu scl(d) sc(__) scl(b) s():(_
## ecsystm_tLu -0.654
## scale(day) -0.292 0.036
## scl(wtr_d_) -0.104 0.272 0.256
## scale(bsln) 0.048 -0.032 -0.007 0.071
## scl(d):(__) 0.145 0.180 -0.241 0.322 0.092
## scl(dy):s() 0.011 0.050 -0.012 0.135 -0.286 0.171
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "species_richness"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -4.8 0.012 ** moderate
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 170.3 193.2 -73.1 146.3 38
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.22 -0.75 -0.02 0.51 2.13
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 1e-01 0.34
## day 4e-04 0.02 -1.00
## Residual 1e+00 1.04
## Number of obs: 50, groups: culture_ID, 10
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 5.74 0.22 41.77 26.0
## ecosystem_typeLarge unconnected 0.97 0.33 42.20 2.9
## scale(day) 0.03 0.25 22.89 0.1
## scale(water_addition_ml) -0.11 0.20 49.75 -0.6
## scale(baseline) -0.04 0.17 42.06 -0.3
## ecosystem_typeLarge unconnected:scale(day) -0.23 0.35 19.36 -0.6
## scale(day):scale(water_addition_ml) -0.20 0.20 49.43 -1.0
## scale(day):scale(baseline) 0.20 0.17 18.28 1.2
## Pr(>|t|)
## (Intercept) <2e-16 ***
## ecosystem_typeLarge unconnected 0.005 **
## scale(day) 0.898
## scale(water_addition_ml) 0.584
## scale(baseline) 0.792
## ecosystem_typeLarge unconnected:scale(day) 0.524
## scale(day):scale(water_addition_ml) 0.321
## scale(day):scale(baseline) 0.248
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Lu scl(d) sc(__) scl(b) e_Lu:( s():(_
## ecsystm_tLu -0.662
## scale(day) -0.087 -0.068
## scl(wtr_d_) -0.102 0.361 -0.024
## scale(bsln) 0.124 -0.337 0.143 -0.281
## ecsys_Lu:() 0.029 0.153 -0.734 0.270 -0.170
## scl(d):(__) 0.162 0.244 -0.443 0.485 -0.368 0.417
## scl(dy):s() 0.020 -0.144 0.198 -0.357 0.155 -0.337 -0.252
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -6.4 0.004 *** strong
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 168.7 189.7 -73.4 146.7 39
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.16 -0.70 0.02 0.46 2.24
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 1e-01 0.37
## day 5e-04 0.02 -1.00
## Residual 1e+00 1.04
## Number of obs: 50, groups: culture_ID, 10
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 5.74 0.22 39.44 25.9 <2e-16
## ecosystem_typeLarge unconnected 1.00 0.33 43.78 3.1 0.004
## scale(day) -0.09 0.17 21.78 -0.5 0.621
## scale(water_addition_ml) -0.07 0.19 49.27 -0.4 0.701
## scale(baseline) -0.06 0.17 41.77 -0.4 0.707
## scale(day):scale(water_addition_ml) -0.15 0.18 45.33 -0.8 0.425
## scale(day):scale(baseline) 0.17 0.16 16.84 1.0 0.319
##
## (Intercept) ***
## ecosystem_typeLarge unconnected **
## scale(day)
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Lu scl(d) sc(__) scl(b) s():(_
## ecsystm_tLu -0.675
## scale(day) -0.092 0.066
## scl(wtr_d_) -0.113 0.334 0.265
## scale(bsln) 0.131 -0.318 0.026 -0.248
## scl(d):(__) 0.166 0.199 -0.220 0.428 -0.332
## scl(dy):s() 0.031 -0.098 -0.075 -0.293 0.111 -0.131
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "evenness_pielou"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 2.3 0.424 none
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## -51.0 -28.0 37.5 -75.0 38
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.1 -0.5 0.1 0.7 1.8
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 4e-02 0.19
## day 1e-04 0.01 -1.00
## Residual 1e-02 0.10
## Number of obs: 50, groups: culture_ID, 10
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 8e-01 2e-02 2e+01 32.5
## ecosystem_typeLarge unconnected -4e-02 4e-02 2e+01 -1.3
## scale(day) 5e-02 4e-02 1e+01 1.4
## scale(water_addition_ml) -5e-02 2e-02 5e+01 -2.2
## scale(baseline) -2e-04 2e-02 2e+01 0.0
## ecosystem_typeLarge unconnected:scale(day) -4e-02 5e-02 1e+01 -0.9
## scale(day):scale(water_addition_ml) -2e-02 2e-02 5e+01 -1.2
## scale(day):scale(baseline) -2e-02 3e-02 1e+01 -0.9
## Pr(>|t|)
## (Intercept) <2e-16 ***
## ecosystem_typeLarge unconnected 0.22
## scale(day) 0.20
## scale(water_addition_ml) 0.03 *
## scale(baseline) 0.99
## ecosystem_typeLarge unconnected:scale(day) 0.41
## scale(day):scale(water_addition_ml) 0.23
## scale(day):scale(baseline) 0.40
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Lu scl(d) sc(__) scl(b) e_Lu:( s():(_
## ecsystm_tLu -0.668
## scale(day) 0.240 -0.249
## scl(wtr_d_) -0.066 0.305 -0.006
## scale(bsln) -0.136 0.291 -0.134 0.101
## ecsys_Lu:() -0.197 0.384 -0.724 0.171 0.149
## scl(d):(__) 0.172 0.209 -0.295 0.487 0.240 0.265
## scl(dy):s() -0.077 0.138 -0.176 0.172 0.348 0.280 0.076
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 1 0.319 none
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## -52.2 -31.2 37.1 -74.2 39
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.3 -0.5 0.2 0.6 1.8
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 4e-02 0.20
## day 1e-04 0.01 -1.00
## Residual 1e-02 0.10
## Number of obs: 50, groups: culture_ID, 10
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.777 0.024 27.616 33.0 <2e-16
## ecosystem_typeLarge unconnected -0.033 0.033 36.552 -1.0 0.31
## scale(day) 0.028 0.026 10.482 1.1 0.31
## scale(water_addition_ml) -0.042 0.021 49.107 -2.1 0.04
## scale(baseline) 0.002 0.017 22.198 0.1 0.91
## scale(day):scale(water_addition_ml) -0.020 0.020 48.969 -1.0 0.31
## scale(day):scale(baseline) -0.016 0.025 8.904 -0.7 0.53
##
## (Intercept) ***
## ecosystem_typeLarge unconnected
## scale(day)
## scale(water_addition_ml) *
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Lu scl(d) sc(__) scl(b) s():(_
## ecsystm_tLu -0.654
## scale(day) 0.143 0.046
## scl(wtr_d_) -0.035 0.266 0.172
## scale(bsln) -0.110 0.257 -0.039 0.079
## scl(d):(__) 0.236 0.123 -0.153 0.465 0.212
## scl(dy):s() -0.023 0.034 0.039 0.129 0.319 0.002
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "median_body_area_µm2"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 1 0.22 none
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 816.7 839.6 -396.3 792.7 38
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.7 -0.6 -0.2 0.7 2.5
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 7e+05 807
## day 2e+03 43 -1.00
## Residual 4e+05 632
## Number of obs: 50, groups: culture_ID, 10
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 3607 136 33 26.6
## ecosystem_typeLarge unconnected -336 191 33 -1.8
## scale(day) -288 185 13 -1.6
## scale(water_addition_ml) -131 120 49 -1.1
## scale(baseline) 70 94 32 0.7
## ecosystem_typeLarge unconnected:scale(day) 6 250 11 0.0
## scale(day):scale(water_addition_ml) 78 118 47 0.7
## scale(day):scale(baseline) 59 122 10 0.5
## Pr(>|t|)
## (Intercept) <2e-16 ***
## ecosystem_typeLarge unconnected 0.09 .
## scale(day) 0.14
## scale(water_addition_ml) 0.28
## scale(baseline) 0.47
## ecosystem_typeLarge unconnected:scale(day) 0.98
## scale(day):scale(water_addition_ml) 0.51
## scale(day):scale(baseline) 0.64
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Lu scl(d) sc(__) scl(b) e_Lu:( s():(_
## ecsystm_tLu -0.662
## scale(day) -0.010 -0.065
## scl(wtr_d_) -0.063 0.293 0.061
## scale(bsln) 0.090 -0.033 -0.065 0.078
## ecsys_Lu:() -0.014 0.159 -0.717 0.128 0.052
## scl(d):(__) 0.243 0.128 -0.338 0.430 0.201 0.294
## scl(dy):s() -0.021 0.033 0.070 0.137 0.128 -0.055 0.007
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -1 0.082 * weak
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 814.7 835.7 -396.3 792.7 39
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.7 -0.6 -0.2 0.7 2.5
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 6e+05 806
## day 2e+03 43 -1.00
## Residual 4e+05 632
## Number of obs: 50, groups: culture_ID, 10
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 3607 136 34 26.6 <2e-16
## ecosystem_typeLarge unconnected -337 189 38 -1.8 0.08
## scale(day) -285 129 12 -2.2 0.05
## scale(water_addition_ml) -131 119 49 -1.1 0.28
## scale(baseline) 70 94 32 0.7 0.47
## scale(day):scale(water_addition_ml) 78 113 48 0.7 0.49
## scale(day):scale(baseline) 60 122 10 0.5 0.64
##
## (Intercept) ***
## ecosystem_typeLarge unconnected .
## scale(day) *
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Lu scl(d) sc(__) scl(b) s():(_
## ecsystm_tLu -0.668
## scale(day) -0.028 0.071
## scl(wtr_d_) -0.062 0.279 0.220
## scale(bsln) 0.091 -0.042 -0.040 0.072
## scl(d):(__) 0.258 0.086 -0.191 0.414 0.194
## scl(dy):s() -0.022 0.042 0.044 0.145 0.131 0.024
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
for(eco_type_i in 1:length(ecosystem_type_selected)){
print(ecosystem_type_selected[eco_type_i])
p = ds_ecosystems %>%
filter(ecosystem_type == ecosystem_type_selected[eco_type_i]) %>%
group_by(day) %>%
summarise(Ble = mean(Ble_indiv_per_ml_dominance, na.rm = TRUE),
Cep = mean(Cep_indiv_per_ml_dominance, na.rm = TRUE),
Col = mean(Col_indiv_per_ml_dominance, na.rm = TRUE),
Eug = mean(Eug_indiv_per_ml_dominance, na.rm = TRUE),
Eup = mean(Eup_indiv_per_ml_dominance, na.rm = TRUE),
Lox = mean(Lox_indiv_per_ml_dominance, na.rm = TRUE),
Pau = mean(Pau_indiv_per_ml_dominance, na.rm = TRUE),
Pca = mean(Pca_indiv_per_ml_dominance, na.rm = TRUE),
Spi = mean(Spi_indiv_per_ml_dominance, na.rm = TRUE),
Spi_te = mean(Spi_te_indiv_per_ml_dominance, na.rm = TRUE),
Tet = mean(Tet_indiv_per_ml_dominance, na.rm = TRUE)) %>%
pivot_longer(Ble:Tet, names_to = "species", values_to = "species_indiv_per_ml") %>%
ggplot(aes(x = day,
y = species_indiv_per_ml,
group = interaction(day, species),
color = species)) +
geom_point(position = position_dodge(dodging),
size = treatment_points_size) +
geom_line(aes(group = species),
position = position_dodge(dodging),
linewidth = treatment_lines_linewidth) +
labs(x = axis_names %>%
filter(variable == "day") %>%
pull(axis_name),
y = axis_names %>%
filter(variable == "dominance") %>%
pull(axis_name)) +
coord_cartesian(ylim = c(0, 100))
print(p)
}
## [1] "Large connected to small"
## [1] "Large unconnected"
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
"water_addition_ml")
ecosystem_type_selected = c("Large connected to small",
"Large connected to large")
response_variable_selected = "shannon"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 2.3 0.42 none
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 37.7 65.5 -6.8 13.7 63
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.78 -0.74 0.04 0.63 2.62
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 5e-02 0.23
## day 1e-04 0.01 -1.00
## Residual 7e-02 0.26
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df
## (Intercept) 1.426 0.042 59.020
## ecosystem_typeLarge connected to small -0.074 0.068 54.480
## scale(day) 0.009 0.045 20.031
## scale(water_addition_ml) -0.045 0.039 70.427
## scale(baseline) 0.006 0.032 53.635
## ecosystem_typeLarge connected to small:scale(day) 0.064 0.076 17.236
## scale(day):scale(water_addition_ml) -0.029 0.038 66.478
## scale(day):scale(baseline) -0.027 0.036 16.331
## t value Pr(>|t|)
## (Intercept) 34.1 <2e-16 ***
## ecosystem_typeLarge connected to small -1.1 0.3
## scale(day) 0.2 0.8
## scale(water_addition_ml) -1.1 0.3
## scale(baseline) 0.2 0.8
## ecosystem_typeLarge connected to small:scale(day) 0.8 0.4
## scale(day):scale(water_addition_ml) -0.8 0.4
## scale(day):scale(baseline) -0.8 0.5
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ec_Lcts scl(d) sc(__) scl(b) e_Lcts: s():(_
## ecsyst_Lcts -0.572
## scale(day) -0.074 0.002
## scl(wtr_d_) 0.268 -0.149 0.260
## scale(bsln) 0.142 -0.286 -0.014 -0.029
## ecs_Lcts:() -0.041 -0.051 -0.535 -0.094 0.026
## scl(d):(__) 0.437 -0.082 -0.091 0.477 -0.032 -0.175
## scl(dy):s() -0.029 0.026 0.160 -0.035 -0.067 -0.282 -0.038
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 1 0.307 none
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 36.4 61.8 -7.2 14.4 64
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.67 -0.72 0.07 0.65 2.59
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 6e-02 0.25
## day 1e-04 0.01 -1.00
## Residual 7e-02 0.26
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 1.428 0.042 57.540 34.1
## ecosystem_typeLarge connected to small -0.070 0.068 55.861 -1.0
## scale(day) 0.029 0.039 22.798 0.8
## scale(water_addition_ml) -0.042 0.039 70.371 -1.1
## scale(baseline) 0.006 0.032 52.980 0.2
## scale(day):scale(water_addition_ml) -0.024 0.038 68.745 -0.6
## scale(day):scale(baseline) -0.019 0.035 16.217 -0.5
## Pr(>|t|)
## (Intercept) <2e-16 ***
## ecosystem_typeLarge connected to small 0.3
## scale(day) 0.5
## scale(water_addition_ml) 0.3
## scale(baseline) 0.9
## scale(day):scale(water_addition_ml) 0.5
## scale(day):scale(baseline) 0.6
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) e_Lcts scl(d) sc(__) scl(b) s():(_
## ecsyst_Lcts -0.575
## scale(day) -0.118 -0.029
## scl(wtr_d_) 0.266 -0.156 0.246
## scale(bsln) 0.143 -0.285 0.000 -0.027
## scl(d):(__) 0.438 -0.094 -0.218 0.470 -0.028
## scl(dy):s() -0.041 0.012 0.010 -0.064 -0.070 -0.091
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "bioarea_mm2_per_ml"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -0.1 0.128 none
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 192.7 220.6 -84.4 168.7 63
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.4 -0.4 0.0 0.4 3.4
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 8e-01 0.87
## day 5e-04 0.02 -1.00
## Residual 4e-01 0.66
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df
## (Intercept) 2.38 0.18 17.51
## ecosystem_typeLarge connected to small -0.69 0.32 15.14
## scale(day) -0.88 0.11 37.52
## scale(water_addition_ml) 0.12 0.10 60.15
## scale(baseline) 0.13 0.15 15.01
## ecosystem_typeLarge connected to small:scale(day) 0.14 0.20 33.87
## scale(day):scale(water_addition_ml) -0.18 0.10 66.25
## scale(day):scale(baseline) -0.02 0.09 32.93
## t value Pr(>|t|)
## (Intercept) 13.2 1e-10 ***
## ecosystem_typeLarge connected to small -2.2 0.05 *
## scale(day) -7.7 3e-09 ***
## scale(water_addition_ml) 1.2 0.23
## scale(baseline) 0.8 0.42
## ecosystem_typeLarge connected to small:scale(day) 0.7 0.49
## scale(day):scale(water_addition_ml) -1.8 0.08 .
## scale(day):scale(baseline) -0.2 0.82
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ec_Lcts scl(d) sc(__) scl(b) e_Lcts: s():(_
## ecsyst_Lcts -0.604
## scale(day) -0.309 0.168
## scl(wtr_d_) 0.159 -0.078 0.263
## scale(bsln) 0.248 -0.408 -0.091 -0.017
## ecs_Lcts:() 0.136 -0.301 -0.550 -0.115 0.125
## scl(d):(__) 0.288 -0.062 -0.137 0.451 0.032 -0.164
## scl(dy):s() -0.097 0.131 0.267 0.026 -0.323 -0.392 -0.080
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -1.6 0.057 * weak
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 191.2 216.7 -84.6 169.2 64
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.4 -0.4 0.0 0.4 3.4
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 8e-01 0.89
## day 5e-04 0.02 -1.00
## Residual 4e-01 0.66
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 2.360 0.178 18.678 13.2
## ecosystem_typeLarge connected to small -0.619 0.303 17.082 -2.0
## scale(day) -0.840 0.096 39.968 -8.7
## scale(water_addition_ml) 0.128 0.099 60.379 1.3
## scale(baseline) 0.112 0.149 15.478 0.7
## scale(day):scale(water_addition_ml) -0.172 0.104 67.147 -1.7
## scale(day):scale(baseline) 0.003 0.086 32.632 0.0
## Pr(>|t|)
## (Intercept) 6e-11 ***
## ecosystem_typeLarge connected to small 0.06 .
## scale(day) 8e-11 ***
## scale(water_addition_ml) 0.20
## scale(baseline) 0.46
## scale(day):scale(water_addition_ml) 0.10
## scale(day):scale(baseline) 0.97
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) e_Lcts scl(d) sc(__) scl(b) s():(_
## ecsyst_Lcts -0.595
## scale(day) -0.289 0.003
## scl(wtr_d_) 0.178 -0.119 0.241
## scale(bsln) 0.235 -0.391 -0.027 -0.003
## scl(d):(__) 0.318 -0.119 -0.276 0.440 0.054
## scl(dy):s() -0.048 0.015 0.066 -0.020 -0.306 -0.158
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "species_richness"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 0.6 0.18 none
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 255.2 283.0 -115.6 231.2 63
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.37 -0.78 0.01 0.54 2.80
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 6e-13 8e-07
## day 1e-15 4e-08 -1.00
## Residual 1e+00 1e+00
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df
## (Intercept) 6.17 0.18 75.00
## ecosystem_typeLarge connected to small -0.48 0.28 75.00
## scale(day) -0.17 0.17 75.00
## scale(water_addition_ml) 0.13 0.17 75.00
## scale(baseline) 0.11 0.13 75.00
## ecosystem_typeLarge connected to small:scale(day) 0.23 0.29 75.00
## scale(day):scale(water_addition_ml) -0.16 0.17 75.00
## scale(day):scale(baseline) -0.02 0.14 75.00
## t value Pr(>|t|)
## (Intercept) 34.3 <2e-16 ***
## ecosystem_typeLarge connected to small -1.7 0.1 .
## scale(day) -1.0 0.3
## scale(water_addition_ml) 0.8 0.5
## scale(baseline) 0.8 0.4
## ecosystem_typeLarge connected to small:scale(day) 0.8 0.4
## scale(day):scale(water_addition_ml) -1.0 0.3
## scale(day):scale(baseline) -0.1 0.9
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ec_Lcts scl(d) sc(__) scl(b) e_Lcts: s():(_
## ecsyst_Lcts -0.556
## scale(day) -0.018 -0.042
## scl(wtr_d_) 0.286 -0.154 0.273
## scale(bsln) -0.004 -0.114 0.013 -0.086
## ecs_Lcts:() -0.090 0.016 -0.506 -0.103 0.032
## scl(d):(__) 0.447 -0.080 -0.098 0.505 -0.158 -0.200
## scl(dy):s() -0.076 0.030 0.033 -0.191 0.024 -0.096 -0.148
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -0.8 0.094 * weak
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 253.9 279.4 -115.9 231.9 64
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.2 -0.8 0.0 0.6 2.8
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 2e-10 1e-05
## day 4e-13 6e-07 -1.00
## Residual 1e+00 1e+00
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 6.181 0.180 75.000 34.4
## ecosystem_typeLarge connected to small -0.480 0.284 75.000 -1.7
## scale(day) -0.105 0.152 75.000 -0.7
## scale(water_addition_ml) 0.145 0.172 75.000 0.8
## scale(baseline) 0.103 0.135 75.000 0.8
## scale(day):scale(water_addition_ml) -0.136 0.166 75.000 -0.8
## scale(day):scale(baseline) -0.005 0.136 75.000 0.0
## Pr(>|t|)
## (Intercept) <2e-16 ***
## ecosystem_typeLarge connected to small 0.1 .
## scale(day) 0.5
## scale(water_addition_ml) 0.4
## scale(baseline) 0.4
## scale(day):scale(water_addition_ml) 0.4
## scale(day):scale(baseline) 1.0
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) e_Lcts scl(d) sc(__) scl(b) s():(_
## ecsyst_Lcts -0.557
## scale(day) -0.074 -0.039
## scl(wtr_d_) 0.279 -0.154 0.257
## scale(bsln) -0.001 -0.115 0.033 -0.084
## scl(d):(__) 0.440 -0.078 -0.235 0.497 -0.155
## scl(dy):s() -0.085 0.031 -0.018 -0.203 0.028 -0.172
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "evenness_pielou"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 3.2 0.661 none
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## -93.8 -66.0 58.9 -117.8 63
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.4 -0.6 0.2 0.7 1.9
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 6e-03 0.077
## day 1e-05 0.004 -1.00
## Residual 1e-02 0.108
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df
## (Intercept) 0.787 0.018 62.245
## ecosystem_typeLarge connected to small -0.004 0.029 59.645
## scale(day) 0.015 0.019 20.222
## scale(water_addition_ml) -0.048 0.017 72.039
## scale(baseline) -0.003 0.014 59.183
## ecosystem_typeLarge connected to small:scale(day) 0.029 0.032 17.657
## scale(day):scale(water_addition_ml) -0.016 0.016 66.785
## scale(day):scale(baseline) -0.018 0.015 17.101
## t value Pr(>|t|)
## (Intercept) 43.7 <2e-16 ***
## ecosystem_typeLarge connected to small -0.2 0.877
## scale(day) 0.8 0.433
## scale(water_addition_ml) -2.8 0.006 **
## scale(baseline) -0.2 0.825
## ecosystem_typeLarge connected to small:scale(day) 0.9 0.376
## scale(day):scale(water_addition_ml) -1.0 0.339
## scale(day):scale(baseline) -1.2 0.248
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ec_Lcts scl(d) sc(__) scl(b) e_Lcts: s():(_
## ecsyst_Lcts -0.600
## scale(day) -0.027 -0.021
## scl(wtr_d_) 0.300 -0.190 0.309
## scale(bsln) 0.268 -0.353 -0.021 0.091
## ecs_Lcts:() -0.103 0.016 -0.551 -0.186 -0.036
## scl(d):(__) 0.482 -0.164 -0.050 0.504 0.200 -0.241
## scl(dy):s() 0.076 -0.034 0.239 0.221 -0.006 -0.364 0.146
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 2 0.873 none
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## -95.0 -69.5 58.5 -117.0 64
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.3 -0.6 0.3 0.6 1.9
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 8e-03 0.090
## day 2e-05 0.004 -1.00
## Residual 1e-02 0.108
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 0.788 0.018 61.148 44.0
## ecosystem_typeLarge connected to small -0.005 0.029 58.481 -0.2
## scale(day) 0.024 0.016 22.734 1.5
## scale(water_addition_ml) -0.045 0.017 72.435 -2.7
## scale(baseline) -0.003 0.014 57.949 -0.2
## scale(day):scale(water_addition_ml) -0.012 0.016 71.076 -0.8
## scale(day):scale(baseline) -0.013 0.014 16.203 -0.9
## Pr(>|t|)
## (Intercept) <2e-16 ***
## ecosystem_typeLarge connected to small 0.872
## scale(day) 0.142
## scale(water_addition_ml) 0.009 **
## scale(baseline) 0.849
## scale(day):scale(water_addition_ml) 0.447
## scale(day):scale(baseline) 0.378
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) e_Lcts scl(d) sc(__) scl(b) s():(_
## ecsyst_Lcts -0.603
## scale(day) -0.104 -0.015
## scl(wtr_d_) 0.289 -0.192 0.248
## scale(bsln) 0.266 -0.353 -0.048 0.087
## scl(d):(__) 0.475 -0.167 -0.222 0.481 0.199
## scl(dy):s() 0.041 -0.030 0.048 0.164 -0.028 0.063
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "median_body_area_µm2"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -7.1 0.004 *** strong
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 1185.0 1212.8 -580.5 1161.0 63
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.9 -0.6 -0.1 0.5 2.7
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 0e+00 0e+00
## day 3e-16 2e-08 NaN
## Residual 3e+05 6e+02
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df
## (Intercept) 3924 89 75
## ecosystem_typeLarge connected to small -344 139 75
## scale(day) 161 86 75
## scale(water_addition_ml) 16 87 75
## scale(baseline) 32 67 75
## ecosystem_typeLarge connected to small:scale(day) -377 141 75
## scale(day):scale(water_addition_ml) 82 85 75
## scale(day):scale(baseline) 103 69 75
## t value Pr(>|t|)
## (Intercept) 44.2 <2e-16 ***
## ecosystem_typeLarge connected to small -2.5 0.016 *
## scale(day) 1.9 0.065 .
## scale(water_addition_ml) 0.2 0.855
## scale(baseline) 0.5 0.636
## ecosystem_typeLarge connected to small:scale(day) -2.7 0.009 **
## scale(day):scale(water_addition_ml) 1.0 0.342
## scale(day):scale(baseline) 1.5 0.139
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ec_Lcts scl(d) sc(__) scl(b) e_Lcts: s():(_
## ecsyst_Lcts -0.554
## scale(day) -0.018 -0.044
## scl(wtr_d_) 0.300 -0.158 0.265
## scale(bsln) 0.027 0.117 -0.031 0.089
## ecs_Lcts:() -0.087 0.014 -0.504 -0.095 -0.041
## scl(d):(__) 0.455 -0.077 -0.099 0.524 0.213 -0.193
## scl(dy):s() 0.121 -0.045 -0.019 0.289 0.045 0.082 0.234
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -2.8 0.029 ** moderate
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 1189.3 1214.8 -583.7 1167.3 64
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.17 -0.59 -0.07 0.45 2.77
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 3e+05 517
## day 6e+02 25 -1.00
## Residual 3e+05 564
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 3910 90 60 43.3
## ecosystem_typeLarge connected to small -348 142 59 -2.5
## scale(day) 40 84 22 0.5
## scale(water_addition_ml) -10 90 71 -0.1
## scale(baseline) 25 68 59 0.4
## scale(day):scale(water_addition_ml) 44 86 67 0.5
## scale(day):scale(baseline) 118 79 17 1.5
## Pr(>|t|)
## (Intercept) <2e-16 ***
## ecosystem_typeLarge connected to small 0.02 *
## scale(day) 0.64
## scale(water_addition_ml) 0.91
## scale(baseline) 0.71
## scale(day):scale(water_addition_ml) 0.61
## scale(day):scale(baseline) 0.15
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) e_Lcts scl(d) sc(__) scl(b) s():(_
## ecsyst_Lcts -0.556
## scale(day) -0.087 -0.039
## scl(wtr_d_) 0.295 -0.163 0.237
## scale(bsln) 0.026 0.116 -0.055 0.084
## scl(d):(__) 0.454 -0.082 -0.210 0.511 0.211
## scl(dy):s() 0.117 -0.044 0.023 0.269 0.013 0.228
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
for(eco_type_i in 1:length(ecosystem_type_selected)){
print(ecosystem_type_selected[eco_type_i])
p = ds_ecosystems %>%
filter(ecosystem_type == ecosystem_type_selected[eco_type_i]) %>%
group_by(day) %>%
summarise(Ble = mean(Ble_indiv_per_ml_dominance, na.rm = TRUE),
Cep = mean(Cep_indiv_per_ml_dominance, na.rm = TRUE),
Col = mean(Col_indiv_per_ml_dominance, na.rm = TRUE),
Eug = mean(Eug_indiv_per_ml_dominance, na.rm = TRUE),
Eup = mean(Eup_indiv_per_ml_dominance, na.rm = TRUE),
Lox = mean(Lox_indiv_per_ml_dominance, na.rm = TRUE),
Pau = mean(Pau_indiv_per_ml_dominance, na.rm = TRUE),
Pca = mean(Pca_indiv_per_ml_dominance, na.rm = TRUE),
Spi = mean(Spi_indiv_per_ml_dominance, na.rm = TRUE),
Spi_te = mean(Spi_te_indiv_per_ml_dominance, na.rm = TRUE),
Tet = mean(Tet_indiv_per_ml_dominance, na.rm = TRUE)) %>%
pivot_longer(Ble:Tet, names_to = "species", values_to = "species_indiv_per_ml") %>%
ggplot(aes(x = day,
y = species_indiv_per_ml,
group = interaction(day, species),
color = species)) +
geom_point(position = position_dodge(dodging),
size = treatment_points_size) +
geom_line(aes(group = species),
position = position_dodge(dodging),
linewidth = treatment_lines_linewidth) +
labs(x = axis_names %>%
filter(variable == "day") %>%
pull(axis_name),
y = axis_names %>%
filter(variable == "dominance") %>%
pull(axis_name)) +
coord_cartesian(ylim = c(0, 100))
print(p)
}
## [1] "Large connected to small"
## [1] "Large connected to large"
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
"water_addition_ml")
ecosystem_type_selected = c("Large connected to large",
"Large unconnected")
response_variable_selected = "shannon"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 3.6 0.811 none
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 23.2 51.0 0.4 -0.8 63
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.3 -0.7 -0.1 0.8 2.7
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 6e-02 0.25
## day 2e-04 0.01 -1.00
## Residual 5e-02 0.23
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 1.475 0.037 63.076 40.0
## ecosystem_typeLarge unconnected -0.002 0.059 58.153 0.0
## scale(day) -0.006 0.044 19.303 -0.1
## scale(water_addition_ml) 0.015 0.037 67.673 0.4
## scale(baseline) 0.018 0.028 57.748 0.6
## ecosystem_typeLarge unconnected:scale(day) 0.047 0.072 14.460 0.7
## scale(day):scale(water_addition_ml) 0.067 0.038 73.272 1.8
## scale(day):scale(baseline) -0.019 0.034 13.723 -0.6
## Pr(>|t|)
## (Intercept) <2e-16 ***
## ecosystem_typeLarge unconnected 0.98
## scale(day) 0.90
## scale(water_addition_ml) 0.69
## scale(baseline) 0.52
## ecosystem_typeLarge unconnected:scale(day) 0.52
## scale(day):scale(water_addition_ml) 0.08 .
## scale(day):scale(baseline) 0.59
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Lu scl(d) sc(__) scl(b) e_Lu:( s():(_
## ecsystm_tLu -0.491
## scale(day) -0.146 0.043
## scl(wtr_d_) 0.163 0.182 0.166
## scale(bsln) 0.111 -0.232 -0.015 -0.062
## ecsys_Lu:() 0.090 -0.002 -0.570 0.093 -0.001
## scl(d):(__) 0.436 0.090 -0.235 0.538 -0.027 0.184
## scl(dy):s() -0.022 0.001 0.132 -0.020 -0.017 -0.229 -0.046
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 2 0.977 none
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 21.6 47.1 0.2 -0.4 64
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.2 -0.6 -0.1 0.7 2.7
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 7e-02 0.27
## day 2e-04 0.01 -1.00
## Residual 5e-02 0.23
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 1.473 0.037 64.013 40.1 <2e-16
## ecosystem_typeLarge unconnected -0.002 0.059 58.787 0.0 1.0
## scale(day) 0.011 0.037 20.805 0.3 0.8
## scale(water_addition_ml) 0.012 0.037 68.178 0.3 0.8
## scale(baseline) 0.018 0.028 58.404 0.6 0.5
## scale(day):scale(water_addition_ml) 0.061 0.037 73.076 1.6 0.1
## scale(day):scale(baseline) -0.013 0.033 14.063 -0.4 0.7
##
## (Intercept) ***
## ecosystem_typeLarge unconnected
## scale(day)
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Lu scl(d) sc(__) scl(b) s():(_
## ecsystm_tLu -0.493
## scale(day) -0.113 0.050
## scl(wtr_d_) 0.158 0.183 0.262
## scale(bsln) 0.111 -0.232 -0.018 -0.062
## scl(d):(__) 0.431 0.092 -0.158 0.534 -0.028
## scl(dy):s() -0.002 0.000 0.002 0.001 -0.016 -0.003
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "bioarea_mm2_per_ml"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 1.2 0.245 none
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 213.2 241.0 -94.6 189.2 63
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.99 -0.45 -0.02 0.36 2.92
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 9e-01 0.97
## day 8e-04 0.03 -1.00
## Residual 6e-01 0.77
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 2.369 0.188 18.575 12.6
## ecosystem_typeLarge unconnected 0.392 0.332 15.428 1.2
## scale(day) -0.870 0.139 37.330 -6.2
## scale(water_addition_ml) 0.008 0.126 61.522 0.1
## scale(baseline) 0.078 0.158 15.541 0.5
## ecosystem_typeLarge unconnected:scale(day) -0.374 0.233 30.404 -1.6
## scale(day):scale(water_addition_ml) -0.138 0.126 62.310 -1.1
## scale(day):scale(baseline) 0.142 0.113 31.752 1.3
## Pr(>|t|)
## (Intercept) 2e-10 ***
## ecosystem_typeLarge unconnected 0.3
## scale(day) 3e-07 ***
## scale(water_addition_ml) 1.0
## scale(baseline) 0.6
## ecosystem_typeLarge unconnected:scale(day) 0.1
## scale(day):scale(water_addition_ml) 0.3
## scale(day):scale(baseline) 0.2
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Lu scl(d) sc(__) scl(b) e_Lu:( s():(_
## ecsystm_tLu -0.583
## scale(day) -0.348 0.199
## scl(wtr_d_) 0.129 0.065 0.226
## scale(bsln) 0.275 -0.426 -0.071 0.083
## ecsys_Lu:() 0.215 -0.316 -0.583 0.023 0.142
## scl(d):(__) 0.308 0.017 -0.196 0.528 0.076 0.092
## scl(dy):s() -0.019 0.142 0.217 0.151 -0.292 -0.406 0.201
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 1.6 0.544 none
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 213.6 239.1 -95.8 191.6 64
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.05 -0.53 -0.04 0.48 2.89
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 1.197 1.09
## day 0.001 0.03 -1.00
## Residual 0.614 0.78
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 2.44 0.19 20.26 13.2 2e-11
## ecosystem_typeLarge unconnected 0.20 0.31 18.63 0.6 0.5
## scale(day) -1.00 0.12 34.26 -8.5 6e-10
## scale(water_addition_ml) 0.01 0.13 60.36 0.1 0.9
## scale(baseline) 0.12 0.16 15.83 0.7 0.5
## scale(day):scale(water_addition_ml) -0.12 0.13 61.71 -0.9 0.4
## scale(day):scale(baseline) 0.07 0.11 27.41 0.6 0.5
##
## (Intercept) ***
## ecosystem_typeLarge unconnected
## scale(day) ***
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Lu scl(d) sc(__) scl(b) s():(_
## ecsystm_tLu -0.547
## scale(day) -0.315 0.017
## scl(wtr_d_) 0.127 0.079 0.288
## scale(bsln) 0.246 -0.400 0.014 0.081
## scl(d):(__) 0.297 0.053 -0.175 0.525 0.062
## scl(dy):s() 0.074 0.016 -0.025 0.170 -0.304 0.254
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "species_richness"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -0.6 0.103 none
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 250.5 278.3 -113.3 226.5 63
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.8 -0.8 -0.1 0.5 2.5
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 0e+00 0e+00
## day 4e-19 6e-10 NaN
## Residual 1e+00 1e+00
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 6.32 0.17 75.00 36.4
## ecosystem_typeLarge unconnected 0.57 0.28 75.00 2.0
## scale(day) -0.28 0.18 75.00 -1.5
## scale(water_addition_ml) 0.24 0.17 75.00 1.4
## scale(baseline) 0.13 0.13 75.00 1.0
## ecosystem_typeLarge unconnected:scale(day) 0.23 0.29 75.00 0.8
## scale(day):scale(water_addition_ml) 0.21 0.17 75.00 1.2
## scale(day):scale(baseline) 0.01 0.13 75.00 0.1
## Pr(>|t|)
## (Intercept) <2e-16 ***
## ecosystem_typeLarge unconnected 0.05 *
## scale(day) 0.13
## scale(water_addition_ml) 0.17
## scale(baseline) 0.32
## ecosystem_typeLarge unconnected:scale(day) 0.42
## scale(day):scale(water_addition_ml) 0.22
## scale(day):scale(baseline) 0.93
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Lu scl(d) sc(__) scl(b) e_Lu:( s():(_
## ecsystm_tLu -0.499
## scale(day) -0.150 0.039
## scl(wtr_d_) 0.149 0.186 0.191
## scale(bsln) 0.121 -0.266 -0.016 -0.088
## ecsys_Lu:() 0.100 0.021 -0.570 0.120 -0.011
## scl(d):(__) 0.420 0.094 -0.275 0.532 -0.048 0.237
## scl(dy):s() -0.063 -0.014 0.171 -0.081 0.007 -0.280 -0.150
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -1.9 0.048 ** moderate
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 249.2 274.7 -113.6 227.2 64
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.8 -0.7 -0.1 0.5 2.5
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 0e+00 0e+00
## day 4e-15 6e-08 NaN
## Residual 1e+00 1e+00
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 6.31 0.17 75.00 36.4 <2e-16
## ecosystem_typeLarge unconnected 0.57 0.28 75.00 2.0 0.05
## scale(day) -0.19 0.15 75.00 -1.3 0.20
## scale(water_addition_ml) 0.22 0.17 75.00 1.3 0.20
## scale(baseline) 0.13 0.13 75.00 1.0 0.32
## scale(day):scale(water_addition_ml) 0.18 0.17 75.00 1.1 0.29
## scale(day):scale(baseline) 0.04 0.13 75.00 0.3 0.74
##
## (Intercept) ***
## ecosystem_typeLarge unconnected *
## scale(day)
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Lu scl(d) sc(__) scl(b) s():(_
## ecsystm_tLu -0.503
## scale(day) -0.114 0.062
## scl(wtr_d_) 0.139 0.185 0.318
## scale(bsln) 0.123 -0.265 -0.027 -0.088
## scl(d):(__) 0.410 0.091 -0.175 0.522 -0.047
## scl(dy):s() -0.036 -0.009 0.014 -0.050 0.004 -0.090
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "evenness_pielou"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 0.3 0.161 none
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## -106.6 -78.8 65.3 -130.6 63
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.37 -0.63 0.07 0.82 1.89
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 1e-02 0.120
## day 4e-05 0.006 -1.00
## Residual 9e-03 0.097
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 8e-01 2e-02 6e+01 52.8
## ecosystem_typeLarge unconnected -5e-02 2e-02 6e+01 -1.9
## scale(day) 2e-02 2e-02 2e+01 1.0
## scale(water_addition_ml) -1e-02 2e-02 7e+01 -0.9
## scale(baseline) 4e-03 1e-02 6e+01 0.4
## ecosystem_typeLarge unconnected:scale(day) -9e-04 3e-02 1e+01 0.0
## scale(day):scale(water_addition_ml) 2e-02 2e-02 7e+01 1.1
## scale(day):scale(baseline) -6e-03 1e-02 1e+01 -0.4
## Pr(>|t|)
## (Intercept) <2e-16 ***
## ecosystem_typeLarge unconnected 0.06 .
## scale(day) 0.33
## scale(water_addition_ml) 0.37
## scale(baseline) 0.69
## ecosystem_typeLarge unconnected:scale(day) 0.98
## scale(day):scale(water_addition_ml) 0.26
## scale(day):scale(baseline) 0.68
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Lu scl(d) sc(__) scl(b) e_Lu:( s():(_
## ecsystm_tLu -0.479
## scale(day) -0.124 0.029
## scl(wtr_d_) 0.177 0.173 0.160
## scale(bsln) 0.016 -0.022 -0.004 0.000
## ecsys_Lu:() 0.076 0.016 -0.561 0.088 0.002
## scl(d):(__) 0.447 0.088 -0.223 0.544 0.009 0.171
## scl(dy):s() 0.033 0.008 -0.002 0.048 0.003 -0.009 0.076
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -1.7 0.056 * weak
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## -108.6 -83.1 65.3 -130.6 64
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.37 -0.62 0.06 0.82 1.88
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 1e-02 0.120
## day 4e-05 0.006 -1.00
## Residual 9e-03 0.097
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.809 0.015 63.261 52.9 <2e-16
## ecosystem_typeLarge unconnected -0.047 0.024 58.968 -1.9 0.06
## scale(day) 0.019 0.016 20.151 1.2 0.25
## scale(water_addition_ml) -0.014 0.016 68.069 -0.9 0.37
## scale(baseline) 0.004 0.011 58.746 0.4 0.69
## scale(day):scale(water_addition_ml) 0.018 0.016 73.867 1.2 0.25
## scale(day):scale(baseline) -0.006 0.014 13.947 -0.4 0.68
##
## (Intercept) ***
## ecosystem_typeLarge unconnected .
## scale(day)
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Lu scl(d) sc(__) scl(b) s():(_
## ecsystm_tLu -0.482
## scale(day) -0.099 0.047
## scl(wtr_d_) 0.172 0.173 0.254
## scale(bsln) 0.016 -0.022 -0.004 0.000
## scl(d):(__) 0.441 0.086 -0.156 0.538 0.009
## scl(dy):s() 0.034 0.008 -0.009 0.049 0.003 0.079
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "median_body_area_µm2"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -14.9 < 0.001 **** very strong
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 1186.5 1214.3 -581.3 1162.5 63
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.04 -0.58 -0.03 0.45 2.56
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 4e+05 634
## day 1e+03 31 -1.00
## Residual 3e+05 538
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 3863 85 64 45.3
## ecosystem_typeLarge unconnected -654 134 60 -4.9
## scale(day) 128 105 20 1.2
## scale(water_addition_ml) -217 87 68 -2.5
## scale(baseline) 100 63 59 1.6
## ecosystem_typeLarge unconnected:scale(day) -434 168 15 -2.6
## scale(day):scale(water_addition_ml) -83 88 74 -0.9
## scale(day):scale(baseline) 4 79 14 0.1
## Pr(>|t|)
## (Intercept) <2e-16 ***
## ecosystem_typeLarge unconnected 9e-06 ***
## scale(day) 0.24
## scale(water_addition_ml) 0.01 *
## scale(baseline) 0.12
## ecosystem_typeLarge unconnected:scale(day) 0.02 *
## scale(day):scale(water_addition_ml) 0.35
## scale(day):scale(baseline) 0.96
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Lu scl(d) sc(__) scl(b) e_Lu:( s():(_
## ecsystm_tLu -0.480
## scale(day) -0.134 0.033
## scl(wtr_d_) 0.173 0.174 0.161
## scale(bsln) -0.024 0.099 -0.019 0.015
## ecsys_Lu:() 0.083 0.007 -0.561 0.094 0.009
## scl(d):(__) 0.442 0.092 -0.229 0.540 0.057 0.177
## scl(dy):s() 0.010 0.009 -0.042 0.055 -0.008 0.101 0.029
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 -11.5 < 0.001 **** very strong
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 1189.9 1215.4 -583.9 1167.9 64
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.15 -0.59 -0.01 0.62 2.63
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 9e+05 965
## day 2e+03 48 -1.00
## Residual 3e+05 536
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 3884 85 63 45.5 <2e-16
## ecosystem_typeLarge unconnected -648 134 60 -4.8 9e-06
## scale(day) -23 102 20 -0.2 0.82
## scale(water_addition_ml) -190 88 66 -2.2 0.03
## scale(baseline) 102 63 60 1.6 0.11
## scale(day):scale(water_addition_ml) -36 89 73 -0.4 0.69
## scale(day):scale(baseline) 25 95 15 0.3 0.80
##
## (Intercept) ***
## ecosystem_typeLarge unconnected ***
## scale(day)
## scale(water_addition_ml) *
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Lu scl(d) sc(__) scl(b) s():(_
## ecsystm_tLu -0.476
## scale(day) -0.096 0.038
## scl(wtr_d_) 0.180 0.176 0.215
## scale(bsln) -0.022 0.099 -0.015 0.016
## scl(d):(__) 0.449 0.095 -0.140 0.546 0.059
## scl(dy):s() 0.001 0.007 0.012 0.038 -0.009 0.009
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
for(eco_type_i in 1:length(ecosystem_type_selected)){
print(ecosystem_type_selected[eco_type_i])
p = ds_ecosystems %>%
filter(ecosystem_type == ecosystem_type_selected[eco_type_i]) %>%
group_by(day) %>%
summarise(Ble = mean(Ble_indiv_per_ml_dominance, na.rm = TRUE),
Cep = mean(Cep_indiv_per_ml_dominance, na.rm = TRUE),
Col = mean(Col_indiv_per_ml_dominance, na.rm = TRUE),
Eug = mean(Eug_indiv_per_ml_dominance, na.rm = TRUE),
Eup = mean(Eup_indiv_per_ml_dominance, na.rm = TRUE),
Lox = mean(Lox_indiv_per_ml_dominance, na.rm = TRUE),
Pau = mean(Pau_indiv_per_ml_dominance, na.rm = TRUE),
Pca = mean(Pca_indiv_per_ml_dominance, na.rm = TRUE),
Spi = mean(Spi_indiv_per_ml_dominance, na.rm = TRUE),
Spi_te = mean(Spi_te_indiv_per_ml_dominance, na.rm = TRUE),
Tet = mean(Tet_indiv_per_ml_dominance, na.rm = TRUE)) %>%
pivot_longer(Ble:Tet, names_to = "species", values_to = "species_indiv_per_ml") %>%
ggplot(aes(x = day,
y = species_indiv_per_ml,
group = interaction(day, species),
color = species)) +
geom_point(position = position_dodge(dodging),
size = treatment_points_size) +
geom_line(aes(group = species),
position = position_dodge(dodging),
linewidth = treatment_lines_linewidth) +
labs(x = axis_names %>%
filter(variable == "day") %>%
pull(axis_name),
y = axis_names %>%
filter(variable == "dominance") %>%
pull(axis_name)) +
coord_cartesian(ylim = c(0, 100))
print(p)
}
## [1] "Large connected to large"
## [1] "Large unconnected"
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
"water_addition_ml")
ecosystem_type_selected = c("Medium unconnected",
"Medium connected to medium")
response_variable_selected = "shannon"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 2.4 0.461 none
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 45.0 72.8 -10.5 21.0 63
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.39 -0.48 0.06 0.76 2.18
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 0e+00 0e+00
## day 5e-18 2e-09 NaN
## Residual 8e-02 3e-01
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 1.374 0.042 75.000 32.8
## ecosystem_typeMedium unconnected -0.034 0.070 75.000 -0.5
## scale(day) 0.011 0.042 75.000 0.3
## scale(water_addition_ml) 0.072 0.042 75.000 1.7
## scale(baseline) 0.037 0.033 75.000 1.1
## ecosystem_typeMedium unconnected:scale(day) -0.082 0.071 75.000 -1.1
## scale(day):scale(water_addition_ml) 0.091 0.042 75.000 2.1
## scale(day):scale(baseline) 0.005 0.033 75.000 0.2
## Pr(>|t|)
## (Intercept) <2e-16 ***
## ecosystem_typeMedium unconnected 0.63
## scale(day) 0.79
## scale(water_addition_ml) 0.09 .
## scale(baseline) 0.26
## ecosystem_typeMedium unconnected:scale(day) 0.25
## scale(day):scale(water_addition_ml) 0.04 *
## scale(day):scale(baseline) 0.87
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Mu scl(d) sc(__) scl(b) e_Mu:( s():(_
## ecsystm_tMu -0.523
## scale(day) -0.024 -0.014
## scl(wtr_d_) 0.186 0.033 0.174
## scale(bsln) -0.113 0.207 -0.029 -0.084
## ecsys_Mu:() -0.035 -0.013 -0.523 0.012 -0.010
## scl(d):(__) 0.320 0.093 -0.086 0.551 0.008 -0.114
## scl(dy):s() -0.009 -0.004 -0.096 0.036 -0.007 0.213 -0.032
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 1.8 0.625 none
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 44.3 69.8 -11.2 22.3 64
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.3 -0.5 0.2 0.8 2.3
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 3e-10 2e-05
## day 6e-13 8e-07 -1.00
## Residual 8e-02 3e-01
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 1.37 0.04 75.00 32.5 <2e-16
## ecosystem_typeMedium unconnected -0.03 0.07 75.00 -0.5 0.63
## scale(day) -0.01 0.04 75.00 -0.4 0.70
## scale(water_addition_ml) 0.07 0.04 75.00 1.7 0.09
## scale(baseline) 0.04 0.03 75.00 1.1 0.27
## scale(day):scale(water_addition_ml) 0.09 0.04 75.00 2.0 0.05
## scale(day):scale(baseline) 0.01 0.03 75.00 0.4 0.68
##
## (Intercept) ***
## ecosystem_typeMedium unconnected
## scale(day)
## scale(water_addition_ml) .
## scale(baseline)
## scale(day):scale(water_addition_ml) *
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Mu scl(d) sc(__) scl(b) s():(_
## ecsystm_tMu -0.524
## scale(day) -0.050 -0.024
## scl(wtr_d_) 0.187 0.033 0.211
## scale(bsln) -0.113 0.207 -0.040 -0.083
## scl(d):(__) 0.318 0.092 -0.172 0.556 0.006
## scl(dy):s() -0.002 -0.002 0.019 0.035 -0.005 -0.008
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "bioarea_mm2_per_ml"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 1.9 0.35 none
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 171.4 199.2 -73.7 147.4 63
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.94 -0.57 -0.08 0.57 3.05
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 3e-01 0.55
## day 3e-04 0.02 -1.00
## Residual 4e-01 0.61
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 1.78 0.12 18.42 14.9
## ecosystem_typeMedium unconnected -0.22 0.22 16.73 -1.0
## scale(day) -0.93 0.10 39.64 -9.4
## scale(water_addition_ml) 0.10 0.09 62.36 1.0
## scale(baseline) 0.02 0.10 16.69 0.2
## ecosystem_typeMedium unconnected:scale(day) 0.24 0.18 38.43 1.3
## scale(day):scale(water_addition_ml) -0.04 0.10 67.57 -0.5
## scale(day):scale(baseline) 0.04 0.09 37.88 0.4
## Pr(>|t|)
## (Intercept) 1e-11 ***
## ecosystem_typeMedium unconnected 0.3
## scale(day) 1e-11 ***
## scale(water_addition_ml) 0.3
## scale(baseline) 0.8
## ecosystem_typeMedium unconnected:scale(day) 0.2
## scale(day):scale(water_addition_ml) 0.7
## scale(day):scale(baseline) 0.7
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Mu scl(d) sc(__) scl(b) e_Mu:( s():(_
## ecsystm_tMu -0.586
## scale(day) -0.206 0.109
## scl(wtr_d_) 0.147 0.015 0.154
## scale(bsln) -0.282 0.480 0.040 -0.042
## ecsys_Mu:() 0.096 -0.214 -0.567 0.024 -0.108
## scl(d):(__) 0.243 0.083 -0.078 0.534 0.036 -0.121
## scl(dy):s() 0.048 -0.104 -0.266 0.041 -0.210 0.484 -0.052
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 1.5 0.487 none
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 171.1 196.5 -74.5 149.1 64
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.92 -0.54 -0.08 0.45 3.15
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 3e-01 0.59
## day 3e-04 0.02 -1.00
## Residual 4e-01 0.62
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 1.76 0.12 19.61 14.8 4e-12
## ecosystem_typeMedium unconnected -0.16 0.21 20.07 -0.7 0.5
## scale(day) -0.86 0.08 39.33 -10.3 1e-12
## scale(water_addition_ml) 0.09 0.09 61.72 1.0 0.3
## scale(baseline) 0.04 0.10 17.41 0.3 0.7
## scale(day):scale(water_addition_ml) -0.03 0.10 67.44 -0.3 0.8
## scale(day):scale(baseline) -0.02 0.08 33.62 -0.2 0.8
##
## (Intercept) ***
## ecosystem_typeMedium unconnected
## scale(day) ***
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Mu scl(d) sc(__) scl(b) s():(_
## ecsystm_tMu -0.580
## scale(day) -0.198 -0.014
## scl(wtr_d_) 0.146 0.021 0.202
## scale(bsln) -0.273 0.469 -0.026 -0.040
## scl(d):(__) 0.259 0.058 -0.178 0.539 0.022
## scl(dy):s() 0.002 0.000 0.011 0.033 -0.197 0.007
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "species_richness"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 2.8 0.544 none
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 271.1 298.9 -123.5 247.1 63
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.75 -0.64 -0.06 0.74 2.03
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 3.568 1.89
## day 0.007 0.08 -1.00
## Residual 1.372 1.17
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 5.7 0.2 26.8 29.2
## ecosystem_typeMedium unconnected -0.1 0.3 23.7 -0.4
## scale(day) -0.3 0.2 17.2 -1.2
## scale(water_addition_ml) 0.3 0.2 62.7 1.7
## scale(baseline) 0.3 0.2 23.7 2.0
## ecosystem_typeMedium unconnected:scale(day) -0.3 0.4 16.0 -0.9
## scale(day):scale(water_addition_ml) 0.1 0.2 66.7 0.7
## scale(day):scale(baseline) 0.2 0.2 15.8 1.1
## Pr(>|t|)
## (Intercept) <2e-16 ***
## ecosystem_typeMedium unconnected 0.67
## scale(day) 0.26
## scale(water_addition_ml) 0.10 .
## scale(baseline) 0.06 .
## ecosystem_typeMedium unconnected:scale(day) 0.41
## scale(day):scale(water_addition_ml) 0.47
## scale(day):scale(baseline) 0.27
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Mu scl(d) sc(__) scl(b) e_Mu:( s():(_
## ecsystm_tMu -0.526
## scale(day) -0.291 0.155
## scl(wtr_d_) 0.163 0.037 0.141
## scale(bsln) -0.070 0.123 0.004 -0.068
## ecsys_Mu:() 0.131 -0.295 -0.541 0.005 -0.040
## scl(d):(__) 0.301 0.086 -0.076 0.525 -0.005 -0.095
## scl(dy):s() 0.002 -0.041 -0.059 -0.006 -0.290 0.130 -0.059
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 1.5 0.475 none
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 269.8 295.3 -123.9 247.8 64
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.75 -0.67 -0.02 0.67 2.05
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 3.922 1.98
## day 0.007 0.09 -1.00
## Residual 1.373 1.17
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 5.7 0.2 30.4 29.5 <2e-16
## ecosystem_typeMedium unconnected -0.2 0.3 39.0 -0.7 0.47
## scale(day) -0.4 0.2 18.9 -1.9 0.07
## scale(water_addition_ml) 0.3 0.2 62.6 1.7 0.10
## scale(baseline) 0.3 0.2 23.4 2.0 0.06
## scale(day):scale(water_addition_ml) 0.1 0.2 67.1 0.6 0.53
## scale(day):scale(baseline) 0.2 0.2 15.7 1.2 0.24
##
## (Intercept) ***
## ecosystem_typeMedium unconnected
## scale(day) .
## scale(water_addition_ml) .
## scale(baseline) .
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Mu scl(d) sc(__) scl(b) s():(_
## ecsystm_tMu -0.513
## scale(day) -0.272 -0.006
## scl(wtr_d_) 0.163 0.040 0.167
## scale(bsln) -0.065 0.116 -0.020 -0.068
## scl(d):(__) 0.318 0.060 -0.149 0.527 -0.008
## scl(dy):s() -0.015 -0.003 0.013 -0.006 -0.299 -0.046
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "evenness_pielou"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 3.6 0.803 none
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## -109.2 -81.4 66.6 -133.2 63
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.5 -0.6 0.1 0.6 1.8
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 1e-10 1e-05
## day 2e-13 5e-07 -1.00
## Residual 1e-02 1e-01
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 0.800 0.015 75.000 53.5
## ecosystem_typeMedium unconnected 0.014 0.025 75.000 0.6
## scale(day) 0.028 0.015 75.000 1.9
## scale(water_addition_ml) 0.013 0.015 75.000 0.9
## scale(baseline) -0.001 0.012 75.000 -0.1
## ecosystem_typeMedium unconnected:scale(day) -0.009 0.025 75.000 -0.4
## scale(day):scale(water_addition_ml) 0.033 0.015 75.000 2.2
## scale(day):scale(baseline) -0.013 0.012 75.000 -1.1
## Pr(>|t|)
## (Intercept) <2e-16 ***
## ecosystem_typeMedium unconnected 0.58
## scale(day) 0.06 .
## scale(water_addition_ml) 0.38
## scale(baseline) 0.90
## ecosystem_typeMedium unconnected:scale(day) 0.72
## scale(day):scale(water_addition_ml) 0.03 *
## scale(day):scale(baseline) 0.29
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Mu scl(d) sc(__) scl(b) e_Mu:( s():(_
## ecsystm_tMu -0.523
## scale(day) -0.026 -0.015
## scl(wtr_d_) 0.186 0.035 0.169
## scale(bsln) -0.112 0.217 -0.030 -0.073
## ecsys_Mu:() -0.031 -0.012 -0.524 0.021 -0.012
## scl(d):(__) 0.317 0.097 -0.092 0.552 0.026 -0.103
## scl(dy):s() 0.008 0.000 -0.101 0.078 -0.008 0.217 0.021
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 1.7 0.577 none
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## -111.1 -85.6 66.5 -133.1 64
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.5 -0.6 0.2 0.6 1.8
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 1e-14 1e-07
## day 3e-17 5e-09 -1.00
## Residual 1e-02 1e-01
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.800 0.015 75.000 53.4 <2e-16
## ecosystem_typeMedium unconnected 0.014 0.025 75.000 0.6 0.58
## scale(day) 0.025 0.013 75.000 2.0 0.05
## scale(water_addition_ml) 0.013 0.015 75.000 0.9 0.38
## scale(baseline) -0.002 0.012 75.000 -0.1 0.90
## scale(day):scale(water_addition_ml) 0.033 0.015 75.000 2.2 0.03
## scale(day):scale(baseline) -0.012 0.012 75.000 -1.0 0.31
##
## (Intercept) ***
## ecosystem_typeMedium unconnected
## scale(day) *
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml) *
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Mu scl(d) sc(__) scl(b) s():(_
## ecsystm_tMu -0.523
## scale(day) -0.050 -0.025
## scl(wtr_d_) 0.186 0.035 0.211
## scale(bsln) -0.112 0.217 -0.043 -0.073
## scl(d):(__) 0.316 0.096 -0.172 0.557 0.024
## scl(dy):s() 0.015 0.003 0.015 0.075 -0.005 0.044
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
response_variable_selected = "median_body_area_µm2"
We want to know whether the connection influenced this response variable. We first start from plotting how this response variable changed in connected and unconnected ecosystems throughout the experiment through its mean ± 95 confidence interval:
# --- PLOT ORIGINAL DATA --- #
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
response_variable_selected)
Following the initial inspection, we proceed to analyse differences among ecosystems. Our first step involves filtering the data to isolate the relevant data for analysis. Specifically, we exclude data points where the response variable couldn’t be computed, as well as time points preceding the initial disturbance and resource flow. Then we plot the data to make sure that what filtered the data in the right way.
# --- FILTER DATA --- #
filtered_data = ds_ecosystems %>%
filter(time_point %in% time_points_model,
ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected)),
!is.na(!!sym("water_addition_ml")))
# --- PLOT FILTERED DATA --- #
plot.ecosystems.points(filtered_data,
ecosystem_type_selected,
response_variable_selected)
Then, given that we have gathered measurements from the same
ecosystem on multiple occasions, we can develop mixed effect models to
examine how the connection influenced this variable. To study the
effects of ecosystem connection we compare two models to a null model
using ANOVA: a full model and a reduced model. In all models, we treat
culture ID as having a random effect on how the slope and intercept of
the relationship between response variable and time, with the slope and
intercept being correlated (Bates et al.
2015). The full model contains the interaction of connection with
time
(Response variable ~ connection * day + (day | culture ID)),
the reduced model contains the connection but without the interaction
with time
(Response variable ~ connection + day + (day | culture ID)),
and the null model doesn’t contain the connection at all
(Response variable ~ day + (day | culture ID)). If any of
the two model comparisons is significant, then ecosystem connection had
an effect.
# --- ADD BASELINES --- #
baselines = ds_ecosystems %>%
filter(time_point == time_point_of_baselines) %>%
select(culture_ID,
all_of(response_variable_selected)) %>%
rename(baseline = all_of(response_variable_selected))
filtered_data = filtered_data %>%
left_join(baselines)
# --- COMPARE FULL, REDUCED, AND NULL MODEL --- #
full_model = lmer(get(response_variable_selected) ~
ecosystem_type * scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
reduced_model = lmer(get(response_variable_selected) ~
ecosystem_type +
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
null_model = lmer(get(response_variable_selected) ~
scale(day) +
scale(water_addition_ml) * scale(day) +
scale(baseline) * scale(day) +
(day | culture_ID),
data = filtered_data,
REML = FALSE,
control = lmerControl(optimizer = "bobyqa"))
Full model vs null model
# --- FULL VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(full_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 3.9 0.941 none
# --- FULL MODEL - SHOW SUMMARY --- #
print(summary(full_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type * scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 1216.7 1244.5 -596.4 1192.7 63
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.9 -0.5 0.0 0.6 3.4
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 1e+06 988
## day 4e+03 64 -1.00
## Residual 4e+05 599
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 3752 131 18 28.7
## ecosystem_typeMedium unconnected 60 230 16 0.3
## scale(day) -55 149 16 -0.4
## scale(water_addition_ml) -52 94 62 -0.6
## scale(baseline) 102 110 16 0.9
## ecosystem_typeMedium unconnected:scale(day) 91 266 15 0.3
## scale(day):scale(water_addition_ml) 20 94 62 0.2
## scale(day):scale(baseline) -111 126 16 -0.9
## Pr(>|t|)
## (Intercept) <2e-16 ***
## ecosystem_typeMedium unconnected 0.8
## scale(day) 0.7
## scale(water_addition_ml) 0.6
## scale(baseline) 0.4
## ecosystem_typeMedium unconnected:scale(day) 0.7
## scale(day):scale(water_addition_ml) 0.8
## scale(day):scale(baseline) 0.4
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Mu scl(d) sc(__) scl(b) e_Mu:( s():(_
## ecsystm_tMu -0.577
## scale(day) 0.540 -0.343
## scl(wtr_d_) 0.128 0.036 0.124
## scale(bsln) 0.229 -0.354 0.107 -0.004
## ecsys_Mu:() -0.357 0.581 -0.585 -0.026 -0.213
## scl(d):(__) 0.246 0.032 -0.053 0.564 0.084 -0.064
## scl(dy):s() 0.121 -0.206 0.228 0.077 0.573 -0.354 0.002
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- FULL MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, full_model)
qqnorm(resid(full_model))
qqline(resid(full_model))
Reduced vs null model
# --- REDUCED VS NULL MODEL - SHOW MODEL STATS --- #
compute.model.stats(reduced_model,
null_model,
"mixed_model") %>%
show.tidy.model.stats(.)
## deltaAIC p_value evidence
## 1 2 0.938 none
# --- REDUCED MODEL - SHOW SUMMARY --- #
print(summary(reduced_model), digits = 1)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: get(response_variable_selected) ~ ecosystem_type + scale(day) +
## scale(water_addition_ml) * scale(day) + scale(baseline) *
## scale(day) + (day | culture_ID)
## Data: filtered_data
## Control: lmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 1214.8 1240.3 -596.4 1192.8 64
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.9 -0.4 0.0 0.6 3.4
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## culture_ID (Intercept) 1e+06 995
## day 4e+03 64 -1.00
## Residual 4e+05 599
## Number of obs: 75, groups: culture_ID, 15
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 3768 122 24 30.8 <2e-16
## ecosystem_typeMedium unconnected 14 187 35 0.1 0.9
## scale(day) -25 121 17 -0.2 0.8
## scale(water_addition_ml) -51 94 62 -0.5 0.6
## scale(baseline) 110 107 18 1.0 0.3
## scale(day):scale(water_addition_ml) 22 94 62 0.2 0.8
## scale(day):scale(baseline) -95 119 16 -0.8 0.4
##
## (Intercept) ***
## ecosystem_typeMedium unconnected
## scale(day)
## scale(water_addition_ml)
## scale(baseline)
## scale(day):scale(water_addition_ml)
## scale(day):scale(baseline)
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) ecs_Mu scl(d) sc(__) scl(b) s():(_
## ecsystm_tMu -0.485
## scale(day) 0.440 -0.005
## scl(wtr_d_) 0.127 0.063 0.134
## scale(bsln) 0.167 -0.289 -0.022 -0.009
## scl(d):(__) 0.239 0.085 -0.111 0.563 0.072
## scl(dy):s() -0.006 0.000 0.027 0.072 0.547 -0.022
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# --- REDUCED MODEL - SHOW RESIDUAL PLOTS --- #
create.res.vs.fit.ecos(filtered_data, reduced_model)
qqnorm(resid(reduced_model))
qqline(resid(reduced_model))
for(eco_type_i in 1:length(ecosystem_type_selected)){
print(ecosystem_type_selected[eco_type_i])
p = ds_ecosystems %>%
filter(ecosystem_type == ecosystem_type_selected[eco_type_i]) %>%
group_by(day) %>%
summarise(Ble = mean(Ble_indiv_per_ml_dominance, na.rm = TRUE),
Cep = mean(Cep_indiv_per_ml_dominance, na.rm = TRUE),
Col = mean(Col_indiv_per_ml_dominance, na.rm = TRUE),
Eug = mean(Eug_indiv_per_ml_dominance, na.rm = TRUE),
Eup = mean(Eup_indiv_per_ml_dominance, na.rm = TRUE),
Lox = mean(Lox_indiv_per_ml_dominance, na.rm = TRUE),
Pau = mean(Pau_indiv_per_ml_dominance, na.rm = TRUE),
Pca = mean(Pca_indiv_per_ml_dominance, na.rm = TRUE),
Spi = mean(Spi_indiv_per_ml_dominance, na.rm = TRUE),
Spi_te = mean(Spi_te_indiv_per_ml_dominance, na.rm = TRUE),
Tet = mean(Tet_indiv_per_ml_dominance, na.rm = TRUE)) %>%
pivot_longer(Ble:Tet, names_to = "species", values_to = "species_indiv_per_ml") %>%
ggplot(aes(x = day,
y = species_indiv_per_ml,
group = interaction(day, species),
color = species)) +
geom_point(position = position_dodge(dodging),
size = treatment_points_size) +
geom_line(aes(group = species),
position = position_dodge(dodging),
linewidth = treatment_lines_linewidth) +
labs(x = axis_names %>%
filter(variable == "day") %>%
pull(axis_name),
y = axis_names %>%
filter(variable == "dominance") %>%
pull(axis_name)) +
coord_cartesian(ylim = c(0, 100))
print(p)
}
## [1] "Medium unconnected"
## [1] "Medium connected to medium"
plot.ecosystems.points(ds_ecosystems,
ecosystem_type_selected,
"water_addition_ml")
We want here to plot the final paper version of the biodiversity and productivity of meta-ecosystems. We need to plot it again instead of using the plots we used in the analysis because we want to change the size of the plot.
# Define meta-ecosystems you want to plot.
metaecosystem_type_selected = c("Medium-Medium",
"Small-Large")
# Write function to plot a response variable. Afterwards you can use this function to plot alpha, beta, gamma diversity, and biomass.
plot.single.plot = function(response_variable_selected){
ds_metaecosystems %>%
filter(metaecosystem_type %in% metaecosystem_type_selected,
!is.na(!!sym(response_variable_selected))) %>%
summarySE(measurevar = response_variable_selected,
groupvars = c("day", "metaecosystem_type", "connection")) %>%
ggplot(aes(x = day,
y = get(response_variable_selected),
group = interaction(day, metaecosystem_type, connection),
color = metaecosystem_type,
linetype = connection)) +
geom_point(stat = "summary",
fun = "mean",
position = position_dodge(dodging),
size = treatment_points_size) +
geom_line(stat = "summary",
fun = "mean",
aes(group = interaction(metaecosystem_type, connection)),
position = position_dodge(dodging),
linewidth = treatment_lines_linewidth) +
geom_errorbar(aes(ymax = get(response_variable_selected) + ci,
ymin = get(response_variable_selected) - ci),
width = width_errorbar,
position = position_dodge(dodging)) +
labs(x = axis_names$axis_name[axis_names$variable == "day"],
y = axis_names$axis_name[axis_names$variable == response_variable_selected],
color = "") +
scale_color_manual(values = treatment_colours) +
scale_linetype_manual(values = treatment_linetype) +
geom_vline(xintercept = resource_flow_days,
linetype = resource_flow_line_type,
color = resource_flow_line_colour,
linewidth = resource_flow_line_width) +
theme_bw() +
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
legend.position = legend_position,
legend.key.width = unit(legend_width_cm, "cm")) +
guides(color = guide_legend(title = NULL,
nrow = 2),
linetype = guide_legend(title = NULL,
nrow = 2)) +
theme(plot.margin = unit(c(ggarrange_margin_left,
ggarrange_margin_right,
ggarrange_margin_bottom,
ggarrange_margin_left),
"cm")) +
geom_rect(xmin = grey_background_xmin,
xmax = grey_background_xmax,
ymin = grey_background_ymin,
ymax = grey_background_ymax,
fill = grey_background_fill,
alpha = grey_background_alpha,
color = grey_background_color)
}
# Combine plots of alpha, beta, gamma biodiversity and biomass.
p_combined = ggarrange(plot.single.plot("mean_shannon") +
rremove("xlab") +
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank()) +
font("legend.text", size = paper_labels_size) +
font("ylab", size = paper_labels_size),
plot.single.plot("bray_curtis") +
rremove("xlab") +
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank()) +
font("legend.text",
size = paper_labels_size) +
font("ylab",
size = paper_labels_size),
plot.single.plot("metaecosystem_richness") +
rremove("xlab") +
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank()) +
font("legend.text",
size = paper_labels_size) +
font("ylab",
size = paper_labels_size),
plot.single.plot("total_metaecosystem_bioarea_mm2") +
font("legend.text",
size = paper_labels_size) +
font("xlab",
size = paper_labels_size) +
font("ylab",
size = paper_labels_size) +
scale_x_continuous(breaks = unique(ds_metaecosystems$day)),
heights = c(0.8, 0.8, 0.8, 1),
nrow = 4,
common.legend = TRUE,
align = "v",
labels = c("(a)", "(b)", "(c)", "(d)"),
label.x = 0.1,
label.y = 0.8) %>%
print()
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's linetype values.
We want here to plot the final paper version of the biodiversity and productivity of the small and large ecosystems. We need to plot it again instead of using the plots we used in the analysis because we want to have the underscores in the legend. We don’t use underscores in the analysis because we can’t easily input them from a level name vector.
# Define ecosystems you want to plot.
ecosystem_type_selected = c("Small connected to large",
"Small connected to small",
"Small unconnected",
"Large connected to small",
"Large connected to large",
"Large unconnected")
# Construct function to plot how the response variable (biomass or Shannon) of small and large ecosystems changes across time.
plot.single.plot = function(response_variable_selected){
ds_ecosystems %>%
filter(ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected))) %>%
summarySE(measurevar = response_variable_selected,
groupvars = c("day", "time_point", "ecosystem_type", "ecosystem_size", "connection")) %>%
ggplot(aes(x = day,
y = get(response_variable_selected),
group = interaction(day, ecosystem_type),
color = ecosystem_type,
linetype = ecosystem_type)) +
geom_point(stat = "summary",
fun = "mean",
position = position_dodge(dodging),
size = treatment_points_size) +
geom_line(stat = "summary",
fun = "mean",
aes(group = ecosystem_type),
position = position_dodge(dodging),
linewidth = treatment_lines_linewidth) +
geom_errorbar(aes(ymax = get(response_variable_selected) + ci,
ymin = get(response_variable_selected) - ci),
width = width_errorbar,
position = position_dodge(dodging)) +
labs(x = axis_names$axis_name[axis_names$variable == "day"],
y = axis_names$axis_name[axis_names$variable == response_variable_selected],
color = "") +
scale_color_manual(values = c("#993404",
"#993404",
"#993404",
"#3182bd",
"#3182bd",
"#3182bd"),
label = expression(S[L],
S[S],
S,
L[S],
L[L],
L)) +
scale_linetype_manual(values = c("solid",
"dashed",
"dotted",
"solid",
"dashed",
"dotted"),
label = expression(S[L],
S[S],
S,
L[S],
L[L],
L)) +
geom_vline(xintercept = resource_flow_days,
linetype = resource_flow_line_type,
color = resource_flow_line_colour,
linewidth = resource_flow_line_width) +
geom_hline(yintercept = 0,
color = zero_line_colour,
linetype = zero_line_line_type,
linewidth = zero_line_line_width) +
theme_bw() +
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
legend.position = legend_position,
legend.key.width = unit(legend_width_cm, "cm")) +
guides(color = guide_legend(title = NULL,
nrow = 3),
linetype = guide_legend(title = NULL,
nrow = 3)) +
geom_rect(xmin = grey_background_xmin,
xmax = grey_background_xmax,
ymin = grey_background_ymin,
ymax = grey_background_ymax,
fill = grey_background_fill,
alpha = grey_background_alpha,
color = grey_background_color)
}
# Combine plots
p_combined = ggarrange(plot.single.plot("shannon") +
rremove("xlab") +
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank()) +
font("legend.text",
size = paper_labels_size) +
font("ylab",
size = paper_labels_size),
plot.single.plot("bioarea_mm2_per_ml") +
font("legend.text",
size = paper_labels_size) +
font("xlab",
size = paper_labels_size) +
font("ylab",
size = paper_labels_size) +
scale_x_continuous(breaks = unique(ds_ecosystems$day)),
heights = c(0.8, 0.8, 1),
nrow = 2,
align = "v",
labels = c("(a)", "(b)"),
label.x = 0.1,
label.y = 0.8,
common.legend = TRUE) %>%
print()
## Warning in qt(conf.interval/2 + 0.5, datac$N - 1): NaNs produced
We want here to plot the final paper version of the biodiversity and productivity of the medium ecosystems. We need to plot it again instead of using the plots we used in the analysis because we want to have the underscores in the legend. We don’t use underscores in the analysis because we can’t easily input them from a level name vector.
# Define ecosystems you want to plot.
ecosystem_type_selected = c("Medium connected to medium",
"Medium unconnected")
# Construct function to plot how the response variable (biomass or Shannon) of small and large ecosystems changes across time.
plot.single.plot = function(response_variable_selected){
ds_ecosystems %>%
filter(ecosystem_type %in% ecosystem_type_selected,
!is.na(!!sym(response_variable_selected))) %>%
summarySE(measurevar = response_variable_selected,
groupvars = c("day", "time_point", "ecosystem_type", "ecosystem_size", "connection")) %>%
ggplot(aes(x = day,
y = get(response_variable_selected),
group = interaction(day, ecosystem_type),
color = ecosystem_type,
linetype = ecosystem_type)) +
geom_point(stat = "summary",
fun = "mean",
position = position_dodge(dodging),
size = treatment_points_size) +
geom_line(stat = "summary",
fun = "mean",
aes(group = ecosystem_type),
position = position_dodge(dodging),
linewidth = treatment_lines_linewidth) +
geom_errorbar(aes(ymax = get(response_variable_selected) + ci,
ymin = get(response_variable_selected) - ci),
width = width_errorbar,
position = position_dodge(dodging)) +
labs(x = axis_names$axis_name[axis_names$variable == "day"],
y = axis_names$axis_name[axis_names$variable == response_variable_selected],
color = "") +
scale_color_manual(values = c("#d95f0e",
"#d95f0e"),
label = expression(M[M],
M)) +
scale_linetype_manual(values = c("dashed",
"dotted"),
label = expression(M[M],
M)) +
geom_vline(xintercept = resource_flow_days,
linetype = resource_flow_line_type,
color = resource_flow_line_colour,
linewidth = resource_flow_line_width) +
geom_hline(yintercept = 0,
color = zero_line_colour,
linetype = zero_line_line_type,
linewidth = zero_line_line_width) +
theme_bw() +
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
legend.position = legend_position,
legend.key.width = unit(legend_width_cm, "cm")) +
guides(color = guide_legend(title = NULL,
nrow = 3),
linetype = guide_legend(title = NULL,
nrow = 3)) +
geom_rect(xmin = grey_background_xmin,
xmax = grey_background_xmax,
ymin = grey_background_ymin,
ymax = grey_background_ymax,
fill = grey_background_fill,
alpha = grey_background_alpha,
color = grey_background_color)
}
# Combine plots
p_combined = ggarrange(plot.single.plot("shannon") +
rremove("xlab") +
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank()) +
font("legend.text",
size = paper_labels_size) +
font("ylab",
size = paper_labels_size),
plot.single.plot("bioarea_mm2_per_ml") +
font("legend.text",
size = paper_labels_size) +
font("xlab",
size = paper_labels_size) +
font("ylab",
size = paper_labels_size) +
scale_x_continuous(breaks = unique(ds_ecosystems$day)),
heights = c(0.8, 0.8, 1),
nrow = 2,
align = "v",
labels = c("(a)", "(b)"),
label.x = 0.1,
label.y = 0.8,
common.legend = TRUE) %>%
print()
We want here to plot the final paper version of the ratio between autotrophic and heterotrophic biomass in small, medium, and large unconnected ecosystems. We need to plot it again instead of using the plots we used in the analysis because we want to have S, M, and L in the legend.
# Define ecosystems and response variable you want to plot.
ecosystem_type_input = c("S",
"M",
"L")
response_variable = "auto_hetero_ratio"
# Construct plot
p = ds_ecosystems %>%
# Manipulate
mutate(ecosystem_type = case_when(ecosystem_type == "Small unconnected" ~ "S",
ecosystem_type == "Medium unconnected" ~ "M",
ecosystem_type == "Large unconnected" ~ "L")) %>%
filter(ecosystem_type %in% ecosystem_type_input,
!is.na(!!sym(response_variable))) %>%
summarySE(measurevar = response_variable,
groupvars = c("day", "ecosystem_type", "ecosystem_size", "connection")) %>%
# Create plot
ggplot(aes(x = day,
y = get(response_variable),
group = interaction(day, ecosystem_type),
color = ecosystem_type)) +
# Points
geom_point(stat = "summary",
fun = "mean",
position = position_dodge(dodging),
size = treatment_points_size) +
geom_errorbar(aes(ymax = get(response_variable) + ci,
ymin = get(response_variable) - ci),
width = width_errorbar,
position = position_dodge(dodging)) +
# Lines
geom_line(stat = "summary",
fun = "mean",
aes(group = ecosystem_type),
position = position_dodge(dodging),
linewidth = treatment_lines_linewidth) +
# Axes and legend
labs(x = axis_names$axis_name[axis_names$variable == "day"],
y = axis_names$axis_name[axis_names$variable == response_variable],
color = "") +
scale_x_continuous(breaks = unique(ds_ecosystems$day)) +
guides(color = guide_legend(title = NULL,
nrow = 1),
linetype = guide_legend(title = NULL,
nrow = 1)) +
scale_color_manual(values = c("#000000",
"#737373",
"#bdbdbd")) +
# Extra graphic elements
theme_bw() +
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
legend.position = legend_position,
legend.key.width = unit(legend_width_cm, "cm"),
axis.title.x = element_text(size = paper_labels_size),
axis.title.y = element_text(size = paper_labels_size),
legend.text = element_text(size = paper_labels_size)) +
geom_rect(xmin = grey_background_xmin,
xmax = grey_background_xmax,
ymin = grey_background_ymin,
ymax = grey_background_ymax,
fill = grey_background_fill,
alpha = grey_background_alpha,
color = grey_background_color) +
geom_hline(yintercept = 0,
color = zero_line_colour,
linetype = zero_line_line_type,
linewidth = zero_line_line_width) +
geom_vline(xintercept = resource_flow_days,
linetype = resource_flow_line_type,
color = resource_flow_line_colour,
linewidth = resource_flow_line_width)
## Warning in qt(conf.interval/2 + 0.5, datac$N - 1): NaNs produced
p
During the experiment we noticed that microwaving ecosystem sub-samples for three minutes to create disturbance caused the evaporation of the ecosystems. However, we don’t know exactly how much evaporated and how much we should refill the ecosystems to bring them back to the original volume. Therefore, here I quantify the evaporation of 5.75 and 6.75 ml of deionised water, which represent low and high disturbance, respectively. For each disturbance level, I microwaved 15 tubes of that disturbance level for three minutes and measured their evaporation. To do so, I weighed the water before the microwaving (weigh tubes, add water, reweigh tubes) and after it (weigh Becker, pour water into it, reweigh Becker).
evaporation.test = read.csv(here("1_experiment", "evaporation_test","evaporation_test_initial.csv"), header = TRUE)
evaporation.test %>%
ggplot(aes (x = as.character(water_pipetted),
y = weight_water_evaporated,
group = interaction(water_pipetted, as.character(rack)),
fill = as.character(rack))) +
geom_boxplot(width = boxplot_width) +
labs(x = "Water volume (ml)" ,
y = "Evaporation (g)",
fill = "Rack replicate")
Furthermore, during the experiment we noticed that microwaving five 6.75 ml ecosystems sub-samples with ten empty tubes for three minutes to create disturbance caused the evaporation of the sub-samples more than if they were with other sub-samples. However, we don’t know exactly how much evaporated and how much we should refill the ecosystems to bring them back to the original volume. Therefore, here I quantify the evaporation of five 6.75 ml sub-samples with ten empty or filled falcon tubes. The weighting was conducted as above.
evaporation.test = read.csv(here("1_experiment", "evaporation_test", "evaporation_test_fill_nofill.csv"), header = TRUE)
evaporation.test %>%
ggplot(aes (x = all_tubes_water,
y = weight_water_evaporated)) +
geom_boxplot(width = boxplot_width) +
labs(x = "Water in the other 10 tubes" ,
y = "Evaporation (g)")
To analyse the videos I took of the ecosystems, I used the package BEMOVI. For this, I had to use the powerful computer. Below is the code utilised for video analysis on the powerful computer.
# Clear workspace
rm(list = ls())
# Set working directory
setwd("/media/mendel-himself/ID_061_Ema2/PatchSizePilot/training")
# Load required libraries
# library(devtools)
# install_github("femoerman/bemovi", ref="master")
library(bemovi)
library(parallel)
library(doParallel)
library(foreach)
# Define memory allocation parameters (in MB)
memory.alloc <- 240000 # Total memory allocated
memory.per.identifier <- 40000 # Memory per identifier
memory.per.linker <- 5000 # Memory per linker
memory.per.overlay <- 60000 # Memory per overlay
# Set paths for tools and particle linker
tools.path <- "/home/mendel-himself/bemovi_tools/" # Path to tools folder
to.particlelinker <- tools.path
# Set directories and file names
to.data <- paste(getwd(), "/", sep = "")
video.description.folder <- "0_video_description/"
video.description.file <- "video_description.txt"
raw.video.folder <- "1_raw/"
raw.avi.folder <- "1a_raw_avi/"
metadata.folder <- "1b_raw_meta/"
particle.data.folder <- "2_particle_data/"
trajectory.data.folder <- "3_trajectory_data/"
temp.overlay.folder <- "4a_temp_overlays/"
overlay.folder <- "4_overlays/"
merged.data.folder <- "5_merged_data/"
ijmacs.folder <- "ijmacs/"
######################################################################
# VIDEO PARAMETERS
# Define video parameters
fps <- 25 # Video frame rate (frames per second)
total_frames <- 125 # Total length of video (frames)
width <- 2048 # Video width (pixels)
height <- 2048 # Video height (pixels)
measured_volume <- 34.4 # Measured volume (microliters) for Leica M205 C with 1.6 fold magnification, sample height 0.5 mm and Hamamatsu Orca Flash 4
pixel_to_scale <- 4.05 # Size of a pixel (micrometers) for Leica M205 C with 1.6 fold magnification, sample height 0.5 mm and Hamamatsu Orca Flash 4
video.format <- "cxd" # Video file format (avi, cxd, mov, tiff)
difference.lag <- 10 # Difference lag
thresholds <- c(13, 255) # Threshold values of pixel intensity (considered a measure of pixel "whiteness") for determining if a pixel belongs to an individual rather than the background
######################################################################
# FILTERING PARAMETERS
# optimized for Perfex Pro 10 stereomicrocope with Perfex SC38800 (IDS UI-3880LE-M-GL) camera
# tested stereomicroscopes: Perfex Pro 10, Nikon SMZ1500, Leica M205 C
# tested cameras: Perfex SC38800, Canon 5D Mark III, Hamamatsu Orca Flash 4
# tested species: Tet, Col, Pau, Pca, Eug, Chi, Ble, Ceph, Lox, Spi
particle_min_size <- 10 # Minimum particle size (pixels)
particle_max_size <- 1000 # Maximum particle size (pixels)
trajectory_link_range <- 3 # Number of adjacent frames for linking particles
trajectory_displacement <- 16 # Maximum displacement of a particle between frames
# Filtering criteria
filter_min_net_disp <- 25 # Minimum net displacement (µm)
filter_min_duration <- 1 # Minimum duration (s)
filter_detection_freq <- 0.1 # Minimum detection frequency (1/s)
filter_median_step_length <- 3 # Minimum median step length (µm)
######################################################################
# VIDEO ANALYSIS
# Check if all tools are installed and set permissions
check_tools_folder(tools.path)
system(paste0("chmod a+x ", tools.path, "bftools/bf.sh"))
system(paste0("chmod a+x ", tools.path, "bftools/bfconvert"))
system(paste0("chmod a+x ", tools.path, "bftools/showinf"))
# Convert video files to compressed avi format
convert_to_avi(to.data,
raw.video.folder,
raw.avi.folder,
metadata.folder,
tools.path,
fps,
video.format)
# Uncomment the following lines for testing
# check_video_file_names(to.data, raw.avi.folder, video.description.folder, video.description.file)
# check_threshold_values(to.data, raw.avi.folder, ijmacs.folder, 2, difference.lag, thresholds, tools.path, memory.alloc)
# Identify particles in the video
locate_and_measure_particles(to.data,
raw.avi.folder,
particle.data.folder,
difference.lag,
min_size = particle_min_size,
max_size = particle_max_size,
thresholds = thresholds,
tools.path,
memory = memory.alloc,
memory.per.identifier = memory.per.identifier,
max.cores = detectCores() - 1)
# Link particles across frames to form trajectories
link_particles(to.data,
particle.data.folder,
trajectory.data.folder,
linkrange = trajectory_link_range,
disp = trajectory_displacement,
start_vid = 1,
memory = memory.alloc,
memory_per_linkerProcess = memory.per.linker,
raw.avi.folder,
max.cores = detectCores() - 1,
max_time = 1)
# Merge video description file with particle data
merge_data(to.data,
particle.data.folder,
trajectory.data.folder,
video.description.folder,
video.description.file,
merged.data.folder)
# Load the merged data
load(paste0(to.data, merged.data.folder, "Master.RData"))
# Filter trajectory data based on defined criteria
trajectory.data.filtered <- filter_data(trajectory.data,
filter_min_net_disp,
filter_min_duration,
filter_detection_freq,
filter_median_step_length)
# Summarize trajectory data to individual-based data
morph_mvt <- summarize_trajectories(trajectory.data.filtered,
calculate.median = F,
write = T,
to.data,
merged.data.folder)
# Summarize sample level data
summarize_populations(trajectory.data.filtered,
morph_mvt,
write = T,
to.data,
merged.data.folder,
video.description.folder,
video.description.file,
total_frames)
# Create overlays for validation
create.subtitle.overlays(to.data,
traj.data = trajectory.data.filtered,
raw.video.folder,
raw.avi.folder,
temp.overlay.folder,
overlay.folder,
fps,
vid.length = total_frames / fps,
width,
height,
tools.path = tools.path,
overlay.type = "number",
video.format)
# Create overlays (old method)
create_overlays(traj.data = trajectory.data.filtered,
to.data = to.data,
merged.data.folder = merged.data.folder,
raw.video.folder = raw.avi.folder,
temp.overlay.folder = "4a_temp_overlays_old/",
overlay.folder = "4_overlays_old/",
width = width,
height = height,
difference.lag = difference.lag,
type = "traj",
predict_spec = F,
contrast.enhancement = 1,
IJ.path = "/home/mendel-himself/bemovi_tools",
memory = memory.alloc,
max.cores = detectCores() - 1,
memory.per.overlay = memory.per.overlay)
To avoid transferring all the data from the powerful computer, I performed species identification on that system and subsequently imported the results into the Rstudio folder on my personal computer. Below is the code utilised for species identification on the powerful computer.
# Clear the workspace
rm(list = ls())
# Uncomment and install required packages if not already installed
#install.packages("e1071",dependencies = T)
#install.packages("devtools",dependencies = T)
#install_github("pennekampster/bemovi", ref="master")
#library(devtools)
# Load required libraries
library(bemovi)
library(e1071)
library("here")
library("tidyverse")
# Define time points in the experiment
time_points_in_experiment = c("t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7")
# Loop through each time point in the experiment
for (time_point in time_points_in_experiment) {
# Define folder names and paths
video.description.folder = "0_video_description/"
video.description.file = "video_description.txt"
merged.data.folder = "5_merged_data/"
monocultures_folder_path = here("biomass_analysis", "training", "")
mixed_cultures_folder_path = here("biomass_analysis", time_point, "")
#Parameters used in the video analysis script
fps = 25
nsv = 5
measured_volume = 34.4
pixel_to_scale = 4.05
filter_min_net_disp = 25
filter_min_duration = 1
filter_detection_freq = 0.1
filter_median_step_length = 3
# Load master dataset of mono-cultures
load(paste0(monocultures_folder_path, merged.data.folder, "Master.RData"))
trajectory.data_monocultures = trajectory.data
rm(trajectory.data)
# Filter the master data of mono-cultures using the same parameters as in the video analysis script
trajectory.data_monocultures.filtered = filter_data(trajectory.data_monocultures,
filter_min_net_disp,
filter_min_duration,
filter_detection_freq,
filter_median_step_length)
# Summarize trajectory data to individual-based data
morph_mvt = summarize_trajectories(data = trajectory.data_monocultures.filtered,
calculate.median = FALSE,
write = TRUE,
to.data = monocultures_folder_path,
merged.data.folder = merged.data.folder) %>%
mutate(comment = NULL)
# Prepare training data by removing incomplete cases
training_data = morph_mvt[complete.cases(morph_mvt), ]
# Train SVM model on the training data
svm1 = svm(
factor(species) ~
mean_grey +
sd_grey +
mean_area +
sd_area +
mean_perimeter +
mean_turning +
sd_turning +
sd_perimeter +
mean_major +
sd_major +
mean_minor +
sd_minor +
mean_ar +
sd_ar +
duration +
max_net +
net_disp +
net_speed +
gross_disp +
max_step +
min_step +
sd_step +
sd_gross_speed +
max_gross_speed +
min_gross_speed ,
data = training_data,
probability = T,
na.action = na.pass)
# Generate and print confusion matrix
confusion.matrix = table(svm1$fitted, training_data$species)
confusion.matrix.nd = confusion.matrix
diag(confusion.matrix.nd) = 0
svm1$confusion = cbind(confusion.matrix,
class.error = rowSums(confusion.matrix.nd) / rowSums(confusion.matrix))
print(paste("Confusion matrix of time point", time_point))
print(svm1$confusion)
# Extract unique species names
species.names = unique(trajectory.data_monocultures$species)
# Load mixed cultures dataset
load(paste0(mixed_cultures_folder_path, merged.data.folder, "Master.RData"))
trajectory.data_mixed = trajectory.data
rm(trajectory.data)
# Filter mixed cultures data using the same parameters
trajectory.data_mixed.filtered = filter_data(trajectory.data_mixed,
filter_min_net_disp,
filter_min_duration,
filter_detection_freq,
filter_median_step_length)
# Summarize trajectory data to individual-based data
morph_mvt = summarize_trajectories(data = trajectory.data_mixed.filtered,
calculate.median = FALSE,
write = TRUE,
to.data = mixed_cultures_folder_path,
merged.data.folder = merged.data.folder)[, which(colnames(morph_mvt) != "Col_manual")] %>%
mutate(comment = NULL)
# Prepare data for prediction by removing incomplete cases
data.to.predict = morph_mvt[complete.cases(morph_mvt),]
# Predict species using the trained SVM model
p.id = predict(object = svm1, data.to.predict, type = "response")
data.to.predict$predicted_species = as.character(p.id)
# Summarize population data
pop.data = summarize_populations(traj.data = trajectory.data_monocultures.filtered,
sum.data = morph_mvt,
write = TRUE,
to.data = mixed_cultures_folder_path,
merged.data.folder = merged.data.folder,
video.description.folder = video.description.folder,
video.description.file = video.description.file,
total_frame = fps * nsv)
# Function to calculate species density
species.density = function(sample_output,
indiv_predicted,
species_names,
total_frames,
mv = measured_volume) {
samples = unique(indiv_predicted$file)
sp.dens = matrix(0,
nrow(sample_output),
length(species_names))
colnames(sp.dens) = species_names
for (i in 1:length(samples)) {
indiv = subset(indiv_predicted, file == samples[i])
spec = unique(indiv$predicted_species)
for (j in 1:length(spec)) {
all.indiv.sp = subset(indiv,
predicted_species == spec[j])
dens = sum(all.indiv.sp$N_frames) / total_frames / mv
sp.dens[which(sample_output$file == as.character(samples[i])), which(species_names == spec[j])] = dens
}
}
return(cbind(sample_output, sp.dens))
}
# Calculate species density for the current time point
output = species.density(pop.data,
data.to.predict,
species.names,
total_frames = fps * nsv,
mv = measured_volume)
# Save the species density results to a CSV file
file_name = paste0("species_ID_", time_point, ".csv")
write.csv(output, here("biomass_analysis", "species_ID_results", file_name))
rm(output)
}
## Time difference of 1.9 mins
Check that disturbance_global_selected is what you set:
print(paste0("Disturbance = ", disturbance_global_selected))
## [1] "Disturbance = high"
If you want to change a certain part of the code using the following code in Unix:
#Rmd script
cd /Users/Ema/Documents/Github/PatchSize/3_r_files
sed -i '' 's/old_string/new_string/g' *.Rmd
#R script
cd /Users/ema/Documents/GitHub/PatchSize/3_r_files/functions
sed -i '' 's/old_string/new_string/g' *.R
you want to share a dataset and get a reproducible object, use the following R code:
dput()
The only type of ecosystem where all cultures crashed was small connected to small at high disturbance.
R.version.string
## [1] "R version 4.3.2 (2023-10-31)"
The R packages we used with their version are as follows:
sessionInfo()
## R version 4.3.2 (2023-10-31)
## Platform: aarch64-apple-darwin20 (64-bit)
## Running under: macOS Sonoma 14.2.1
##
## Matrix products: default
## BLAS: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.11.0
##
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
##
## time zone: Europe/Zurich
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices datasets utils methods base
##
## other attached packages:
## [1] conflicted_1.2.0 broom.mixed_0.2.9.5 emmeans_1.10.4
## [4] combinat_0.0-8 Rmisc_1.5.1 betapart_1.6
## [7] vegan_2.6-6.1 lattice_0.22-6 permute_0.9-7
## [10] glmmTMB_1.1.10 lmerTest_3.1-3 lme4_1.1-35.4
## [13] Matrix_1.6-5 GGally_2.2.1 gridExtra_2.3
## [16] plotly_4.10.4 ggpubr_0.6.0 lubridate_1.9.3
## [19] forcats_1.0.0 stringr_1.5.1 dplyr_1.1.4
## [22] purrr_1.0.2 readr_2.1.5 tidyr_1.3.1
## [25] tibble_3.2.1 ggplot2_3.5.1 tidyverse_2.0.0
## [28] plyr_1.8.9 renv_1.0.7.9000 testthat_3.2.1.1
## [31] here_1.0.1
##
## loaded via a namespace (and not attached):
## [1] RColorBrewer_1.1-3 rstudioapi_0.16.0 jsonlite_1.8.8
## [4] magrittr_2.0.3 estimability_1.5.1 farver_2.1.2
## [7] nloptr_2.1.1 rmarkdown_2.27 vctrs_0.6.5
## [10] memoise_2.0.1 minqa_1.2.7 rstatix_0.7.2
## [13] htmltools_0.5.8.1 itertools_0.1-3 broom_1.0.6
## [16] pracma_2.4.4 sass_0.4.9 parallelly_1.38.0
## [19] bslib_0.7.0 htmlwidgets_1.6.4 desc_1.4.3
## [22] cachem_1.1.0 TMB_1.9.15 lifecycle_1.0.4
## [25] minpack.lm_1.2-4 iterators_1.0.14 pkgconfig_2.0.3
## [28] optimx_2023-10.21 R6_2.5.1 fastmap_1.2.0
## [31] rbibutils_2.2.16 future_1.34.0 magic_1.6-1
## [34] digest_0.6.36 numDeriv_2016.8-1.1 colorspace_2.1-0
## [37] furrr_0.3.1 rprojroot_2.0.4 pkgload_1.3.4
## [40] crosstalk_1.2.1 labeling_0.4.3 fansi_1.0.6
## [43] timechange_0.3.0 httr_1.4.7 abind_1.4-5
## [46] mgcv_1.9-0 compiler_4.3.2 withr_3.0.0
## [49] backports_1.5.0 carData_3.0-5 ggstats_0.6.0
## [52] highr_0.11 ggsignif_0.6.4 MASS_7.3-60
## [55] tools_4.3.2 ape_5.8 glue_1.7.0
## [58] rcdd_1.6 nlme_3.1-163 grid_4.3.2
## [61] cluster_2.1.4 generics_0.1.3 snow_0.4-4
## [64] gtable_0.3.5 tzdb_0.4.0 data.table_1.15.4
## [67] hms_1.1.3 car_3.1-2 utf8_1.2.4
## [70] foreach_1.5.2 pillar_1.9.0 splines_4.3.2
## [73] tidyselect_1.2.1 knitr_1.47 reformulas_0.3.0
## [76] xfun_0.45 brio_1.1.5 stringi_1.8.4
## [79] lazyeval_0.2.2 yaml_2.3.8 boot_1.3-30
## [82] evaluate_0.24.0 codetools_0.2-20 cli_3.6.3
## [85] geometry_0.4.7 Rdpack_2.6.1 munsell_0.5.1
## [88] jquerylib_0.1.4 Rcpp_1.0.12 doSNOW_1.0.20
## [91] globals_0.16.3 coda_0.19-4.1 parallel_4.3.2
## [94] picante_1.8.2 listenv_0.9.1 viridisLite_0.4.2
## [97] mvtnorm_1.3-1 scales_1.3.0 rlang_1.1.4
## [100] cowplot_1.1.3 fastmatch_1.1-4 waldo_0.5.2